状況
Oracle11.2.0.2.0の大量のデータに対する中規模のクエリのクエリ実行プランに問題があります。物事をスピードアップするために、私はおおよそ次のようなことをする範囲フィルターを導入しました:
PROCEDURE DO_STUFF(
org_from VARCHAR2 := NULL,
org_to VARCHAR2 := NULL)
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((org_from IS NULL) OR (org_from <= org.no))
AND ((org_to IS NULL) OR (org_to >= org.no)))
-- [...]
ご覧のとおり、オプションの範囲の組織番号JOIN
の使用を制限したいと思います。organisations
クライアントコードはDO_STUFF
、制限付き(高速と想定)または制限なし(非常に低速)で呼び出すことができます。
トラブル
問題は、PL / SQLが上記のバインド変数org_from
とorg_to
パラメータを作成することです。これは、ほとんどの場合に予想されることです。
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((:B1 IS NULL) OR (:B1 <= org.no))
AND ((:B2 IS NULL) OR (:B2 >= org.no)))
-- [...]
回避策
この場合のみ、値をインライン化するだけで、つまりOracleによって実行されるクエリが実際には次のようなものである場合に、クエリ実行プランがはるかに優れていると測定しました。
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((10 IS NULL) OR (10 <= org.no))
AND ((20 IS NULL) OR (20 >= org.no)))
-- [...]
「たくさん」とは、5〜10倍速いという意味です。クエリが実行されることは非常にまれであることに注意してください。つまり、月に1回です。したがって、実行プランをキャッシュする必要はありません。
私の質問
PL / SQLで値をインライン化するにはどうすればよいですか?EXECUTE IMMEDIATEについては知っていますが、文字列の連結ではなく、PL/SQLにクエリをコンパイルしてもらいたいと思います。
偶然に起こったことを測定しただけですか、それとも変数のインライン化の方が実際に優れていると思いますか(この場合)?私が尋ねる理由は、バインド変数がOracleに一般的な実行プランを考案させるのに対し、インライン化された値は非常に特定の列とインデックスの統計を分析できると思うからです。ですから、これは単なる偶然ではないと想像できます。
私は何かが足りないのですか?変数のインライン化以外に、クエリ実行プランの改善を実現するまったく別の方法があるかもしれません(私もかなりの数のヒントを試しましたが、私はその分野の専門家ではありません)?