oracle 穩定執行計劃 spm 之二 自主綁定、解綁

os: centos 7.4
db: oracle 11.2.0.4

版本

# cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core) 
# 
# su - oracle
Last login: Tue Jan 21 03:40:05 CST 2020 on pts/0
$ sqlplus / as sysdba;

SQL*Plus: Release 11.2.0.4.0 Production on Mon Feb 3 10:29:09 2020

Copyright (c) 1982, 2013, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

SQL> set lines 300;
SQL> set pages 300;
SQL> 
SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE	11.2.0.4.0	Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

SQL> 

準備基礎數據

# su - oracle
$ sqlplus system/oracle

SQL> set lines 500;
set pages 500;


SQL> create table tmp_t0 (
  id   integer,
  name varchar(100)
)
;

SQL> insert into tmp_t0
 select level,dbms_random.string('a',20)
   from dual
connect by level <=1000000
;

commit;

SQL> declare
  v_id   integer;
  v_name varchar2(100);
begin
  for c_f in (
     select      9 as id from dual union all  
     select     99 as id from dual union all
     select    999 as id from dual union all
     select   9999 as id from dual union all
     select  99999 as id from dual union all
     select 999999 as id from dual
  )
  loop
     execute immediate 'select id,name from tmp_t0 where 1=1 and id=:a' into v_id,v_name using c_f.id;
  end loop;
end;
/

查找 SQL_ID 及執行計劃

SQL> select sql_text,sql_id from v$sqlarea sa where 1=1 and sa."SQL_TEXT" like 'select id,name from tmp_t0%';

SQL_TEXT	                            SQL_ID
select id,name from tmp_t0 where 1=1 and id=:a	3m2k16z7wwz0u


SQL> select * from v$sql_plan sp where 1=1 and sp."SQL_ID"='3m2k16z7wwz0u';

可以看到 TABLE ACCESS FULL

spm 固化執行計劃

SQL> set serverout on;
declare
  v_temp number;
begin
  v_temp := dbms_spm.load_plans_from_cursor_cache(
              sql_id=>'3m2k16z7wwz0u', 
			  plan_hash_value=>1652152861
			);
  dbms_output.put_line(v_temp);
end;
/

SQL> commit;

查看spm

SQL> select sql_handle,plan_name,origin,enabled,accepted,to_char(sql_text) sql_text from dba_sql_plan_baselines;

SQL_HANDLE		       PLAN_NAME		      ORIGIN	     ENA ACC
------------------------------ ------------------------------ -------------- --- ---
SQL_TEXT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_b4eef12eee3c0831	       SQL_PLAN_b9vrj5vr3s21j273ab46a MANUAL-LOAD    YES YES
select id,name from tmp_t0 where 1=1 and id=:a

創建索引後查看執行計劃

SQL> create index idx_tmp_t0_id on tmp_t0(id); 

再次執行

SQL> declare
  v_id   integer;
  v_name varchar2(100);
begin
  for c_f in (
     select      9 as id from dual union all  
     select     99 as id from dual union all
     select    999 as id from dual union all
     select   9999 as id from dual union all
     select  99999 as id from dual union all
     select 999999 as id from dual
  )
  loop
     execute immediate 'select id,name from tmp_t0 where 1=1 and id=:a' into v_id,v_name using c_f.id;
  end loop;
end;
/


發現從 v$sql_plan 並沒有找到有SQL使用 IDX_TMP_T0_ID 索引,

SPM 重新綁定使用索引的執行計劃

先清除之前綁定的信息

SQL> set serverout on;
declare
  v_temp number;
begin
  v_temp := dbms_spm.drop_sql_plan_baseline(
                sql_handle=>'SQL_b4eef12eee3c0831', 
				plan_name=>'SQL_PLAN_b9vrj5vr3s21j273ab46a'
			);
  dbms_output.put_line(v_temp);
end;
/

SQL> commit;

再執行一遍

SQL> declare
  v_id   integer;
  v_name varchar2(100);
begin
  for c_f in (
     select      9 as id from dual union all  
     select     99 as id from dual union all
     select    999 as id from dual union all
     select   9999 as id from dual union all
     select  99999 as id from dual union all
     select 999999 as id from dual
  )
  loop
     execute immediate 'select id,name from tmp_t0 where 1=1 and id=:a' into v_id,v_name using c_f.id;
  end loop;
end;
/

SQL> select * from v$sqlarea sa where 1=1 and sa.sql_id='3m2k16z7wwz0u'

會留意到 VERSION_COUNT=2,再查看

SQL> select * from v$sql_plan sp where 1=1 and sp."SQL_ID"='3m2k16z7wwz0u';

重新固化


SQL> set serverout on;
declare
  v_temp number;
begin
  v_temp := dbms_spm.load_plans_from_cursor_cache(
              sql_id=>'3m2k16z7wwz0u', 
			  plan_hash_value=>3728389598
			);
  dbms_output.put_line(v_temp);
end;
/

SQL> commit;

參考:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章