1

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 では発生しません。

4

1 に答える 1

0

私のコメントは少し軽薄だったので、もう少し詳しく説明します。ここでは、SQL システムと特定のクエリの最適化を改善するための一般的なヒントをいくつか紹介します。

  • まず第一に、@GordonLinoff は正しい (いつものように) 小さなテーブルから意味のあるものは何も得られません。オプティマイザーは、異なる方法で動作することを認識しており、動作します。

  • 次に、適切なサイズのテーブル (メモリに応じて少なくとも 50k 行) を作成した後、テーブルで統計を実行するか、オプティマイザー (およびインデックス) が機能しないことを確認する必要があります。

  • 3 番目に、ツールを使用し、実行計画を理解する方法を学ぶ必要があります。システムが何を伝えているかを深く理解していなければ、これらの手法を上達させることはできません。最新の sql データベースには、クエリを調べてインデックスを提案するツールがあります。多くのことを学ぶことができる実行計画と同じように、それらを使用してください。これらのツールは絶対確実ではないことに注意してください。提案を試して、機能するかどうかを確認する必要があります。

  • 最後に、たくさん読んでください。私が特に興味深いと思う情報源の 1 つは、explainextended でブログを書いている stackoverflow ユーザーQuassnoiです。最近はあまり活発ではありませんが、このブログ (および彼の回答の多く) は非常に示唆に富んでいますが、楽しんでいただけると思います。このテーマに関する多くのブログや本があり、少しでも役に立ちます。

この場合、より大きなテーブルの場合、インデックスに列を追加するだけでうまくいくと思います(これには、DBとデータモデルについて多くのことがわかっていないという警告があります)-しかし、Oracleツールを使用してそれが示唆するものを参照してください。まずそれを試してください。

于 2015-11-10T00:24:27.380 に答える