3

この形式のクエリは、平均して約 100 個の in 句要素を使用し、まれに 1000 個を超える要素を使用します。要素が 1000 を超える場合は、in 句を 1000 (Oracle の最大値) に分割します。

SQL の形式は次のとおりです。

SELECT * FROM tab WHERE PrimaryKeyID IN (1,2,3,4,5,...)

私が選択しているテーブルは巨大で、in 句にあるものよりも数百万行多く含まれています。私の懸念は、オプティマイザがテーブル スキャンを実行することを選択する可能性があることです (データベースには最新の統計情報がありません - そうです - わかっています ...)

主キーの使用を強制するために渡すことができるヒントはありますか?主キーのインデックス名を知らなくても、おそらく ... /*+ DO_NOT_TABLE_SCAN */?

そのようなデータを引き戻すための創造的なアプローチはありますか?

  1. 往復回数が最も少ない
  2. 最小数のブロックを読み取ります (論理 IO レベルで?)
  3. これで速くなるのか..
SELECT * FROM tab WHERE PrimaryKeyID = 1
  UNION
SELECT * FROM tab WHERE PrimaryKeyID = 2
  UNION
SELECT * FROM tab WHERE PrimaryKeyID = 2
  UNION ....
4

1 に答える 1

6

WHEREテーブルの統計が正確である場合、句にハードコーディングされた要素が 1000 個しかない場合に、オプティマイザーが主キー インデックスを使用する代わりにテーブル スキャンを実行することを選択する可能性はほとんどありません。最良のアプローチは、オブジェクトの正確な統計を収集 (または設定) することです。これにより、誤った統計を回避するために多くの体操を行うのではなく、自動的に良いことが起こるはずです。

オプティマイザが主キー インデックスを使用するよりもテーブル スキャンの方が効率的であると信じるほど統計が不正確であると仮定した場合DYNAMIC_SAMPLING、オプティマイザがより正確に収集するように強制するヒントを追加できる可能性があります。ステートメントを最適化する前の統計、またはCARDINALITYオプティマイザのデフォルトのカーディナリティ推定をオーバーライドするためのヒント。どちらも、使用可能なインデックスについて何も知る必要はありません。テーブルのエイリアス (またはエイリアスがない場合は名前) を知る必要があるだけです。 DYNAMIC_SAMPLINGより安全で堅牢なアプローチになりますが、解析ステップに時間がかかります。

句内に可変数のハードコーディングされたパラメーターを使用して SQL ステートメントを構築している場合IN、共有プールを共有不可能な SQL であふれさせ、データベースに 1 つのコストを強制的に費やすことで、パフォーマンスの問題を引き起こす可能性があります。各バリアントを個別に解析するのに多くの時間がかかります。一度解析できる単一の共有可能な SQL ステートメントを作成すると、はるかに効率的になります。IN句の値がどこから来ているかによって、次のようになります

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM global_temporary_table);

また

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM TABLE( nested_table ));

また

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM some_other_source);

単一の共有可能な SQL ステートメントに落ち着いた場合、ステートメントを絶えず再解析するコストを回避することに加えて、SQL ステートメントの変更を伴わない特定の計画を強制するための多くのオプションがあります。Oracle のバージョンが異なれば、プランの安定性のためのオプションも異なります。リリースに応じて、その他のテクノロジーの中でも、アウトラインの保存SQL プランの管理、およびSQL プロファイルがあります。これらを使用して、特定の SQL ステートメントに対して特定の計画を強制することができます。ただし、再解析が必要な新しい SQL ステートメントを生成し続けると、これらのテクノロジを使用することが非常に難しくなります。

于 2014-04-01T22:31:34.193 に答える