0

我有以下查询:

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,但是当我运行整个查询时,它变成了全表扫描,这要慢得多。

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

4

3 回答 3

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, ' ', '')));

后

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

于 2012-10-07T23:20:36.833 回答
1
  • 如果您只运行子查询,它不会像父查询那样使用过滤器中的 id 列,因此可以使用索引。在父查询中,您也使用了 id,这会阻止使用索引。也许添加索引(id, upper(replace(c5, ' ', '')))可以解决问题。

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

  • 总是检查性能而不是解释计划。有你的提示可能比没有提示时表现更差。甲骨文并不愚蠢。

于 2012-10-07T23:44:09.947 回答
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
于 2012-10-07T22:49:42.367 回答