一個sql,通過spm固定它的執行計劃,可以通過dbms_spm.load_plans_from_cursor_cache實現。也可以通地此功能在不修改原sql的情況下對其加hint來固定執行計劃。
db version:oracle 11.2.0.4
os:centos 6.6
例如:
原sql走索引:
select * from scott.tb_spm where object_id=10;
想通過加hint讓其走全表掃描:
select /*+full(tb_spm)*/* from scott.tb_spm where object_id=10;
在v$sql中查詢出,原sql的sql_id=064qcdmgt6thw,加hint的sql的sql_id=ahdtbgvsd3bht,plan_hash_value=970476072。
執行以下:
declare
? cnt?? number;
? v_sql clob;
begin
? –得到原語句sql文本
? select sql_fulltext into v_sql from v$sql where sql_id = ‘064qcdmgt6thw’ and rownum=1;
? –用加hint的sql的sql_id和plan_hash_value,來固定原語句的sql
? cnt := dbms_spm.load_plans_from_cursor_cache(sql_id????????? => ‘ahdtbgvsd3bht’,
?????????????????????????????????????????????? plan_hash_value => 970476072,
?????????????????????????????????????????????? sql_text??????? => v_sql);
end;
這樣就將加hint的執行計劃固定在原語句上。執行原語句,在v$sql的plan_hash_value列和sql_plan_baseline列來確認是否固定。
測試中發現,一些含有綁定變量的sql,用常量的sql的sql_id和plan_hash_value無法固定,此時可以嘗試使用execute immediate來生成含有綁定變量的sql。
例如:
declare
? v_sql varchar2(3000);
begin
? v_sql := ‘select /*+full(tb_spm)*/* from scott.tb_spm where object_id=:1’;
? execute immediate v_sql
??? using 10;
end;
或
var v number;
exec :v :=10
select /*+full(tb_spm)*/* from scott.tb_spm where object_id=:v;