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
  • サブクエリのみを実行している場合は、親クエリのようにフィルタのid列を使用しないため、インデックスを使用できます。親クエリでは、IDも使用しているため、インデックスは使用されません。たぶん、インデックスを追加すること(id, upper(replace(c5, ' ', '')))で問題が解決するでしょう。

  • Gaurav Soniは正しいです。目標を達成するために、サブクエリは必要ありません。

  • 説明計画ではなく、常にパフォーマンスを確認してください。ヒントがある場合は、ない場合よりもパフォーマンスが最悪になる可能性があります。オラクルは愚かではありません。

于 2012-10-07T23:44:09.947 に答える
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テーブルを2回使用して、インデックスが使用されているフィルター条件からレコードを取得し、それに基づいて結合するとインデックスの使用が妨げられるため、同じテーブルでの内部結合を避けるように求めている理由、id列にインデックスがないため、これは単純なフィルター条件で実行できます。全表スキャンの同じ問題が再び見つかった場合、またはこのクエリから同じ結果が得られなかった場合は、お知らせください。

于 2012-10-07T23:20:36.833 に答える
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 に答える