EXECUTEIMMEDIATEを使用して呼び出しているストアドプロシージャがあります。私が直面している問題は、プロシージャを直接呼び出す場合と、EXECUTEIMMEDIATEを使用してプロシージャを呼び出す場合とでExplain計画が異なることです。これにより、実行時間が5倍になります。プラン間の主な違いは、すぐに実行を使用すると、オプティマイザーがサブクエリのネストを解除しないことです(NOT EXISTS条件を使用しています)。ここではほとんどのクエリでルールベースのオプティマイザーを使用していますが、これにはインデックスを使用するためのヒントがあり、CBOが使用されています(ただし、テーブルの統計は収集されません)。Oracle9iEnterpriseEditionリリース9.2.0.4.0-64ビット本番環境を実行しています。
例:高速:
begin
package.procedure;
end;
/
遅い:
begin
execute immediate 'begin package.' || proc_name || '; end;';
end;
/
クエリ:
SELECT /*+ INDEX(A IDX_A_1) */
a.store_cd,
b.itm_cd itm_cd,
CEIL ( (new_date - a.dt) / 7) week_num,
SUM (a.qty * b.demand_weighting * b.CONVERT) qty
FROM a
INNER JOIN
b
ON (a.itm_cd = b.old_itm_cd)
INNER JOIN
(SELECT g.store_grp_cd, g.store_cd
FROM g, h
WHERE g.store_grp_cd = h.fdo_cd AND h.fdo_type = '1') d
ON (a.store_cd = d.store_cd AND b.store_grp_cd = d.store_grp_cd)
CROSS JOIN
dow
WHERE a.dt BETWEEN dow.new_date - 91 AND dow.new_date - 1
AND a.sls_wr_cd = 'W'
AND b.demand_type = 'S'
AND b.old_itm_cd IS NOT NULL
AND NOT EXISTS
(SELECT
NULL
FROM f
WHERE f.store_grp_cd = a.store_cd
AND b.old_itm_cd = f.old_itm_cd)
GROUP BY a.store_cd, b.itm_cd, CEIL ( (dow.new_date - a.dt) / 7)
良い説明計画:
操作オプションOBJECT_NAMEOBJECT_TYPEID PARENT_ID ステートメント0を選択 グループを10で並べ替える ネストされたループ21 HASH JOIN ANTI 3 2 インデックスROWIDH43によるテーブルアクセス ネストされたループ54 ネストされたループ65 ネストされたループ76 テーブルアクセスフルB87 INDEX ROWID A97によるテーブルアクセス インデックス範囲スキャンIDX_A_1一意109 INDEX UNIQUE SCAN G UNIQUE 11 6 INDEX RANGE SCAN H_UK UNIQUE 12 5 テーブルアクセスフルF133 テーブルアクセスフルダウ142
悪い説明計画:
操作オプションOBJECT_NAMEOBJECT_TYPEID PARENT_ID ステートメント0を選択 グループを10で並べ替える ネストされたループ21 ネストされたループ32 ネストされたループ43 ネストされたループ54 テーブルアクセスフルB65 INDEX ROWID A75によるテーブルアクセス インデックス範囲スキャンIDX_A_1一意87 テーブルアクセスフルF98 INDEX UNIQUE SCAN G UNIQUE 10 4 インデックスROWIDH113によるテーブルアクセス INDEX RANGE SCAN H_UK UNIQUE 12 11 テーブルアクセスフルダウ132
悪い説明プランでは、サブクエリはネストされていません。サブクエリにno_unnestヒントを追加することで、悪い計画を再現することができました。ただし、(すぐに実行を使用してプロシージャを実行する場合)最も悪いヒントを使用して適切な計画を再現することはできませんでした。他のヒントは、最悪のヒントではなく、即時実行を使用するときにオプティマイザーによって考慮されています。
この問題は、executeimmediateを使用してプロシージャを呼び出す場合にのみ発生します。クエリ自体に対して即時実行を使用する場合は、適切な計画が使用されます。