計画の索引付けと説明は非常に新しいので、ご容赦ください。クエリを調整しようとしていますが、問題が発生しています。
私は2つのテーブルを持っています:
SKU
------
SKUIDX (Unique index)
CLRIDX (Index)
..
..
IMPCOST_CLR
-----------
ICCIDX (Unique index)
CLRIDX (Index)
...
..
select * from SKU where clridx = 122
を実行すると、Explainプランでインデックスを使用していることがわかります(TABLE ACCESS .. INDEXと表示され、OBJECT_NAMEの下にインデックス名が表示され、オプションはRANGE SCANです)。
同じフィールドで結合しようとすると、インデックスを使用していないように見えます(TABLE ACCESS .. HASH JOINと表示され、オプションの下にFULLと表示されます)。
インデックスを使用していない理由を確認するには、何を探す必要がありますか?申し訳ありませんが、これを表示するために入力するコマンドがわかりません。詳細が必要な場合はお知らせください。
例:
最初のクエリ:
SELECT
*
FROM
AP21.SKU
WHERE
CLRIDX = 100
2番目のクエリ:
SELECT
*
FROM
AP21.IMPCOST_CLR
WHERE
CLRIDX = 100
3番目のクエリ:
SELECT
*
FROM
AP21.SKU
INNER JOIN
AP21.IMPCOST_CLR ON
IMPCOST_CLR.CLRIDX = SKU.CLRIDX
このクエリを見てください:
SELECT
*
FROM
AP21.SKU
INNER JOIN
AP21.IMPCOST_CLR ON
IMPCOST_CLR.CLRIDX = SKU.CLRIDX
追加の述語はありません。したがって、SKUのすべての行をIMPCOST_CLRのすべての行に結合します。さらに、両方のテーブルからすべての列を選択しています。
これは、Oracleが両方のテーブル全体を読み取る必要があることを意味します。これを行う最も効率的な方法は、全表スキャンを使用して、マルチブロック読み取りですべての行をすくい上げ、ハッシュを使用して結合の値を一致させることです。
基本的に、これは集合演算であり、SQLが非常にうまく機能しますが、インデックス付きの読み取りはもっと [〜#〜] rbar [〜#〜] です。ここで、3番目のクエリを変更して、次のような追加の述語を含めると、
WHERE SKU.CLRIDX = 100
ほとんどの場合、アクセスパスがINDEX RANGESCANに戻ります。比較的少数の行しか選択していないため、インデックス付きの読み取りが再びより効率的なパスになります。
「調整しようとしているクエリは何百もの長いものですが、それを分解して段階的に実行します!」
これは優れた手法ですが、Oracleオプティマイザがどのように機能するかを理解する必要があります。 ExplainPlanにはたくさんの情報があります。 詳細をご覧ください。 各ステップのRows
列の値に注意してください。これは、オプティマイザーが操作から取得すると予想する行数を示しています。最初の2つのクエリの値は、3番目のクエリとは大きく異なります。
同じフィールドで結合しようとすると、インデックスを使用していないように見えます(TABLE ACCESS .. HASH JOINと表示され、オプションの下にFULLと表示されます)。
これは、HASH JOINが結合述部でインデックスを使用(必要)しないためです。
http://use-the-index-luke.com/sql/join/hash-join-partial-objects