when句の一部がis nullになる単純な結合ステートメントがあります。ステートメントはアプリケーションによって生成されます。this is null制約があると、クエリ プランに問題が発生します。StackExchange の記事で説明されているアプローチに従い、列の複合インデックス (null 許容型と結合するインデックス) を作成しました。インデックス付きの列のみを選択する場合にのみ役立ちます。インデックスのない列を選択すると、それは無視されますが、クエリの結果は同じです (行が選択されていないなど)。
私たちが見る唯一のオプションは、アプリケーションのロジックを変更することですが、これをデータベースレベルで解決する方法がまだあるのでしょうか?
--Illustrative sample. Prepare tables and indexes:
create table tableA
(
Acol1 varchar2(32) NOT NULL,
Acol2 varchar2(32),
Acol3 varchar2(32)
);
insert into tableA (Acol1, Acol2, Acol3)
values ('abcd1','abcd2A','abcd3A');
create table tableB
(
Bcol1 varchar2(32) NOT NULL,
Bcol2 varchar2 (32),
Bcol3 varchar2 (32)
);
insert into tableB (Bcol1, Bcol2, Bcol3)
values ('abcd1','abcd2B','abcd3B');
create index tableA_col12 on tableA (acol1, acol2);
create index tableB_col1 on tableB (Bcol1);
commit;
次に、計画を確認します。
1.
select a.Acol1 from tableA a join tableB b on a.Acol1 = b.Bcol1 where Acol2 is null;
--no rows selected
Plan1 - 範囲スキャン
2.
select * from tableA a join tableB b on a.Acol1 = b.Bcol1 where Acol2 is null;
--no rows selected
Plan2 (上記と同じリンク) - 全表スキャン
クエリを変更する、よりスマートなインデックスを使用する、固定計画を適用するなど、パフォーマンスを向上させる最善の方法はどれでしょうか?
*更新* この質問を準備している間に、サンプルの計画が自動的に変更されました。現在、 Plan2 の代わりにPlan2*があります - 完全なテーブル スキャンはありません。ただし、サンプルを再作成すると (テーブルを削除して再度準備する)、プランは再び Plan2 (フル テーブル スキャン) になります。このトリックは、実際の DB では発生しません。