如何加快查询速度?
How can I speed up the query?
我怎样才能加快这个查询?
l_string varchar2(200);
/* parameter string */
l_string := ':27.07.2015:10.07.2015:23.07.2015:01.08.2015:';
select t3.*
from table1 t1, table2 t2, table3 t3
where t1.col1 = t2.col2
and t2.col3 = t3.col4
and (instr(l_string, ':' || to_char(t3.col1, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col2, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col3, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col4, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col5, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col6, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col7, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col8, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col9, 'dd.mm.yyyy') || ':') > 0 );
我没有要测试的 Oracle 实例,但是 OR
条件几乎总是会减慢执行速度,就像多次调用 instr
一样。尝试进行一次大型串联并在其中搜索值。您会注意到我添加了一个“~”,以确保您没有从数据中获得匹配,因为连接:
select t3.*
from table1 t1, table2 t2, table3 t3
where t1.col1 = t2.col2
and t2.col3 = t3.col4
and instr(l_string,
(':' || to_char(t3.col1, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col2, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col3, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col4, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col5, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col6, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col7, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col8, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col9, 'dd.mm.yyyy') || ':') > 0
我会探索其他选择,但没有更多信息,我只能提供这些。
您使用 instr 的谓词不允许索引访问。因此,您将以 T3 的完整 table 扫描结束。
您可以将谓词表述为不同的形式:
where col1 in (to_date('27.07.2015','dd.mm.yyyy'),
to_date('10.07.2015','dd.mm.yyyy'),
to_date('23.07.2015','dd.mm.yyyy'),
to_date('01.08.2015','dd.mm.yyyy')) or
col2 in (to_date('27.07.2015','dd.mm.yyyy'),
to_date('10.07.2015','dd.mm.yyyy'),
to_date('23.07.2015','dd.mm.yyyy'),
to_date('01.08.2015','dd.mm.yyyy')) or
col3 in (to_date('27.07.2015','dd.mm.yyyy'),
to_date('10.07.2015','dd.mm.yyyy'),
to_date('23.07.2015','dd.mm.yyyy'),
to_date('01.08.2015','dd.mm.yyyy')) or
.... -- etc for columns col3 - col9
如果 table T3 很大并且上面的谓词只选择了很少的记录,您可以通过在 col1 到 col9
上定义索引来获利
create index t3_ix1 on t3(col1);
create index t3_ix2 on t3(col2);
....
可能的执行计划会进行9 * 3(列*值)次INDEX RANGE SCAN和BITMAP CONVERSION得到OR结果。所以对于真正巨大的 T3,27 索引范围扫描会比 FULL SCAN 更好,你会加速;但这取决于您的数据...
我怎样才能加快这个查询?
l_string varchar2(200);
/* parameter string */
l_string := ':27.07.2015:10.07.2015:23.07.2015:01.08.2015:';
select t3.*
from table1 t1, table2 t2, table3 t3
where t1.col1 = t2.col2
and t2.col3 = t3.col4
and (instr(l_string, ':' || to_char(t3.col1, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col2, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col3, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col4, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col5, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col6, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col7, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col8, 'dd.mm.yyyy') || ':') > 0 OR
instr(l_string, ':' || to_char(t3.col9, 'dd.mm.yyyy') || ':') > 0 );
我没有要测试的 Oracle 实例,但是 OR
条件几乎总是会减慢执行速度,就像多次调用 instr
一样。尝试进行一次大型串联并在其中搜索值。您会注意到我添加了一个“~”,以确保您没有从数据中获得匹配,因为连接:
select t3.*
from table1 t1, table2 t2, table3 t3
where t1.col1 = t2.col2
and t2.col3 = t3.col4
and instr(l_string,
(':' || to_char(t3.col1, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col2, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col3, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col4, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col5, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col6, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col7, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col8, 'dd.mm.yyyy') || ':' ||
'~:' || to_char(t3.col9, 'dd.mm.yyyy') || ':') > 0
我会探索其他选择,但没有更多信息,我只能提供这些。
您使用 instr 的谓词不允许索引访问。因此,您将以 T3 的完整 table 扫描结束。 您可以将谓词表述为不同的形式:
where col1 in (to_date('27.07.2015','dd.mm.yyyy'),
to_date('10.07.2015','dd.mm.yyyy'),
to_date('23.07.2015','dd.mm.yyyy'),
to_date('01.08.2015','dd.mm.yyyy')) or
col2 in (to_date('27.07.2015','dd.mm.yyyy'),
to_date('10.07.2015','dd.mm.yyyy'),
to_date('23.07.2015','dd.mm.yyyy'),
to_date('01.08.2015','dd.mm.yyyy')) or
col3 in (to_date('27.07.2015','dd.mm.yyyy'),
to_date('10.07.2015','dd.mm.yyyy'),
to_date('23.07.2015','dd.mm.yyyy'),
to_date('01.08.2015','dd.mm.yyyy')) or
.... -- etc for columns col3 - col9
如果 table T3 很大并且上面的谓词只选择了很少的记录,您可以通过在 col1 到 col9
上定义索引来获利 create index t3_ix1 on t3(col1);
create index t3_ix2 on t3(col2);
....
可能的执行计划会进行9 * 3(列*值)次INDEX RANGE SCAN和BITMAP CONVERSION得到OR结果。所以对于真正巨大的 T3,27 索引范围扫描会比 FULL SCAN 更好,你会加速;但这取决于您的数据...