防止全表扫描

时间:2012-10-07 22:23:42

标签: oracle optimization

我有以下查询:

select id,
       c1,
       c2,
       c3 
from tbl t1
join 
(select id 
   from tbl t2
   where upper(replace(c5, ' ', '')) like upper(?)
) j 
on j.id = t1.id

?是一些通配符参数字符串,如%test%

c5列包含用于访问它的函数的索引:

create index tbl_c5_idx on tbl(upper(replace(c5, ' ', '')))

当我运行内部查询时,它使用tbl_c5_idx,但是当我运行整个查询时,它变成了全表扫描,这要慢得多。

有没有办法避免全表扫描?提示或重写连接条件。我无法重写整个查询,因为内部查询是根据输入条件动态构造的。

3 个答案:

答案 0 :(得分:1)

测试功能的一个非常基本的示例

create table test(id number,value varchar2(200));

insert into test values(1,'gaurav is bad guy');
insert into test values(2,'gaurav is good guy');

SELECT *
FROM test
WHERE UPPER (REPLACE (VALUE, ' ', '')) LIKE UPPER ('%gauravisbad%');

在创建索引之前,这显然是full table scan,因为没有创建索引。

create index tbl_c5_idx on test(upper(replace(value, ' ', '')));

after

我要求你避免在同一个表上进行内部联接的原因是因为你曾经两次使用该表来从你的过滤条件中获取你的记录,然后使用你的索引然后加入{ {1}}阻止使用索引,因为你没有id列的索引,这可以通过一个简单的过滤条件来完成。 如果您再次发现相同的全表扫描问题,或者您未从此查询中获得相同的结果,请与我们联系。

答案 1 :(得分:1)

  • 如果您只运行子查询,它不会像父查询那样使用过滤器中的id列,因此可以使用索引。在父查询中,您也使用id,这会阻止使用索引。也许在(id, upper(replace(c5, ' ', '')))上添加索引可以解决问题。

  • Gaurav Soni是对的:你不需要子查询来实现你的目标。

  • 总是检查表演而不是解释计划。你的提示表现可能比没有表现更差。 Oracle NOT 愚蠢。

答案 2 :(得分:0)

似乎我找到了解决方案,或者至少是有帮助的东西。

我使用了index提示,因此使用tbl_c5_idx进行访问。

这就是最终查询现在的样子:

select /*+ index(t1) */ id,
       c1,
       c2,
       c3 
from tbl t1
join 
(select id 
   from tbl t2
   where upper(replace(c5, ' ', '')) like upper(?)
) j 
on j.id = t1.id