DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE手工替换绑定执行计划
使用SPM与sql profile一样功能:通过手工构造执行计划替换绑定
--创建测试表
SQL> create table tb1 as select * from dba_objects where object_id is not null;
Table created.
SQL> select count(1) from tb1;
COUNT(1)
----------
72533
SQL> update tb1 set object_id=66 where rownum<72533;
72532 rows updated.
SQL> commit;
Commit complete.
SQL> update tb1 set object_id=77 where object_id<>66;
1 row updated.
SQL> commit;
Commit complete.
SQL> create index idx_tb1_object_id on tb1(object_id);
Index created.
SQL> exec dbms_stats.gather_table_stats('AIKI','TB1',cascade=>true,method_opt=>'for columns object_id size 1');
PL/SQL procedure successfully completed.
--77只有1条,执行计划为全表扫描,因为直方图未开导致CBO错误预估了结果集
SQL> var aa number;
SQL> exec :aa :=77;
PL/SQL procedure successfully completed.
SQL> select status from tb1 where object_id=:aa;
STATUS
-------
VALID
SQL> @all
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 2hn00xzrv5t77, child number 6
-------------------------------------
select status from tb1 where object_id=:aa
Plan hash value: 3226679318
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 290 (100)| |
|* 1 | TABLE ACCESS FULL| TB1 | 36267 | 283K| 290 (1)| 00:00:04 |
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / TB1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=:AA)
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "STATUS"[VARCHAR2,7]
28 rows selected.
--手工构造正确的执行计划,并记录下sql_id和plan_hash_value
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 4jqbhqxt090yp, child number 0
-------------------------------------
select /*+ index(tb1(object_id)) */status from tb1 where object_id=:aa
Plan hash value: 455808360
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 589 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TB1 | 36267 | 283K| 589 (1)| 00:00:08 |
|* 2 | INDEX RANGE SCAN | IDX_TB1_OBJECT_ID | 36267 | | 71 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / TB1@SEL$1
2 - SEL$1 / TB1@SEL$1
--关键的执行步骤
--先导入全表扫的计划到baseline
DECLARE
k1 pls_integer;
begin
k1 := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (
sql_id=>'2hn00xzrv5t77',
plan_hash_value=>3226679318,
fixed=>'NO',
enabled=>'YES');
end;
/
--手工构造执行计划,将前面运行的手工构造的SQL计划进行替换绑定
SQL> show user
USER is "AIKI"
SQL> declare
2 k1 pls_integer;
3 begin
4 k1:=DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (
5 sql_id=>'4jqbhqxt090yp',
6 plan_hash_value=>455808360,
7 sql_handle=>'SQL_e1f977ef3e9546c4',--原来不正确BASELINE
8 fixed=>'NO',
9 enabled=>'YES');
10 end;
11 /
PL/SQL procedure successfully completed.
--修改fix属性(也可以采用将没用的baseline,将其drop掉)
SQL>
SQL> declare
2 k1 pls_integer;
3 begin
4 k1:=DBMS_SPM.ALTER_SQL_PLAN_BASELINE (
5 sql_handle=>'SQL_e1f977ef3e9546c4',
6 plan_name=>'SQL_PLAN_f3ybrxwz9ajq4be29918e',
7 attribute_name=>'FIXED',
8 attribute_value=>'YES');
9 end;
10 /
PL/SQL procedure successfully completed.
--检查生效
SQL> show user
USER is "AIKI"
SQL> var aa number;
SQL> exec :aa :=77;
PL/SQL procedure successfully completed.
SQL> select status from tb1 where object_id=:aa;
STATUS
-------
VALID
SQL> var aa number;
SQL> exec :aa :=77;
PL/SQL procedure successfully completed.
SQL> select status from tb1 where object_id=:aa;
STATUS
-------
VALID
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 2hn00xzrv5t77, child number 6
-------------------------------------
select status from tb1 where object_id=:aa
Plan hash value: 455808360
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 589 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TB1 | 36267 | 283K| 589 (1)| 00:00:08 |
|* 2 | INDEX RANGE SCAN | IDX_TB1_OBJECT_ID | 36267 | | 71 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / TB1@SEL$1
2 - SEL$1 / TB1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=:AA)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "STATUS"[VARCHAR2,7]
2 - "TB1".ROWID[ROWID,10]
Note
-----
- SQL plan baseline SQL_PLAN_f3ybrxwz9ajq4be29918e used for this statement
35 rows selected.
--可以看到人工构造的执行计划已经生效了;
DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE手工替换绑定执行计划
最新推荐文章于 2025-06-11 09:55:56 发布