我有一個使用EXECUTE IMMEDIATE調用的存儲過程。我面臨的問題是,當我直接調用過程時,解釋計劃與我使用EXECUTE IMMEDIATE調用過程時不同。這導致執行時間增加5倍。計劃之間的主要區別在於,當我立即使用執行時,優化器不會解除子查詢(我正在使用NOT EXISTS條件)。我們在大多數查詢中都使用基於規則優化器,但是這個提示使用索引,因此正在使用CBO(但是,我們不收集表上的統計信息)。我們正在運行Oracle9i企業版版本9.2.0.4.0 - 64位生產。Oracle EXECUTE IMMEDIATE更改查詢查詢計劃
舉例: 快速:
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)
好解釋計劃:
OPERATION OPTIONS OBJECT_NAME OBJECT_TYPE ID PARENT_ID SELECT STATEMENT 0 SORT GROUP BY 1 0 NESTED LOOPS 2 1 HASH JOIN ANTI 3 2 TABLE ACCESS BY INDEX ROWID H 4 3 NESTED LOOPS 5 4 NESTED LOOPS 6 5 NESTED LOOPS 7 6 TABLE ACCESS FULL B 8 7 TABLE ACCESS BY INDEX ROWID A 9 7 INDEX RANGE SCAN IDX_A_1 UNIQUE 10 9 INDEX UNIQUE SCAN G UNIQUE 11 6 INDEX RANGE SCAN H_UK UNIQUE 12 5 TABLE ACCESS FULL F 13 3 TABLE ACCESS FULL DOW 14 2
不好解釋計劃:
OPERATION OPTIONS OBJECT_NAME OBJECT_TYPE ID PARENT_ID SELECT STATEMENT 0 SORT GROUP BY 1 0 NESTED LOOPS 2 1 NESTED LOOPS 3 2 NESTED LOOPS 4 3 NESTED LOOPS 5 4 TABLE ACCESS FULL B 6 5 TABLE ACCESS BY INDEX ROWID A 7 5 INDEX RANGE SCAN IDX_A_1 UNIQUE 8 7 TABLE ACCESS FULL F 9 8 INDEX UNIQUE SCAN G UNIQUE 10 4 TABLE ACCESS BY INDEX ROWID H 11 3 INDEX RANGE SCAN H_UK UNIQUE 12 11 TABLE ACCESS FULL DOW 13 2
在惡劣的解釋計劃子查詢不被嵌套的。我能夠通過給子查詢添加一個no_unnest提示來重現這個不好的計劃;但是,我無法使用unnest提示(使用立即執行運行該程序時)重現該良好計劃。其他提示正在被優化器考慮時使用立即執行而不是無條件的提示。
只有當我使用立即執行調用該過程時纔會出現此問題。如果我在查詢本身使用立即執行,它使用良好的計劃。
我會認爲基於規則的oprimizer應該是一致的。 可能會添加一個提示,看看這是否也改變了計劃 - 驗證RBO實際上是有效的... – Randy 2010-05-07 16:15:49
我們有一個提示,在查詢中已經使用了一個索引,這樣做會導致CBO被用來代替查詢?儘管如此,我還是試圖在子查詢中加入一些無關緊要的暗示,但這似乎並不令人滿意。 – Gunny 2010-05-07 16:23:57
索引提示不會導致使用CBO。您可以使用FIRST_ROWS或ALL_ROWS提示來強制使用CBO,或使用RULE提示來強制使用RBO。 也許你應該發佈實際的SQL查詢和你看到的兩個不同的計劃。 – 2010-05-07 17:27:50