您的位置:首页 > 其它

如何固定执行计划

2014-06-29 11:56 459 查看
在遭遇执行计划不稳定或者执行计划错误的情况下,通过baseline来固定SQL执行计划以确保执行计划稳定性、提高性能。baseline是oracle 11G提供的稳固sql执行计划的功能,是spm功能的一部分。

步骤如下:

[html] view
plaincopy

SQL> set linesize 1000  

SQL> col index_name for a40  

SQL> col COLUMN_NAME for a20  

SQL> select index_name,COLUMN_NAME from dba_ind_columns where table_name='TEST_PART' and table_owner='TEST_DBA';  

  

INDEX_NAME                               COLUMN_NAME  

---------------------------------------- --------------------  

IND_PART_DT                              DT  

  

SQL>   

此表由索引,可以测试走做引以及走全表扫描  

SQL> set autotrace on explain  

SQL> set pagesize 300  

SQL> set  linesize 300  

SQL> var name1 varchar2(10);  

SQL> var name2 varchar2(100);  

SQL> var name1 varchar2(100);     

SQL> exec :name1 :='2012-09-21 8:05:55';   

  

PL/SQL procedure successfully completed.  

  

SQL> exec :name2 :='2012-09-21 8:06:05';  

  

PL/SQL procedure successfully completed.  

SQL> select * from TEST_DBA.TEST_PART where dt>=to_date(:name1,'yyyy-mm-dd hh24:mi:ss') and  

  2  dt<to_date(:name2,'yyyy-mm-dd hh24:mi:ss') ;  

  

        ID STR        DT  

---------- ---------- ---------  

     29155 aaaaaaaaa  21-SEP-12  

     29156 aaaaaaaaa  21-SEP-12  

     29157 aaaaaaaaa  21-SEP-12  

     29158 aaaaaaaaa  21-SEP-12  

     29159 aaaaaaaaa  21-SEP-12  

     29160 aaaaaaaaa  21-SEP-12  

     29161 aaaaaaaaa  21-SEP-12  

     29162 aaaaaaaaa  21-SEP-12  

     29163 aaaaaaaaa  21-SEP-12  

     29164 aaaaaaaaa  21-SEP-12  

  

10 rows selected.  

  

  

Execution Plan  

----------------------------------------------------------  

Plan hash value: 2229598636  

  

-------------------------------------------------------------------------------------------------------------------  

| Id  | Operation                           | Name        | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |  

-------------------------------------------------------------------------------------------------------------------  

|   0 | SELECT STATEMENT                    |             |   250 |  5750 |     5   (0)| 00:00:01 |       |       |  

|*  1 |  FILTER                             |             |       |       |            |          |       |       |  

|   2 |   PARTITION RANGE ITERATOR          |             |   250 |  5750 |     5   (0)| 00:00:01 |   KEY |   KEY |  

|   3 |    TABLE ACCESS BY LOCAL INDEX ROWID| TEST_PART   |   250 |  5750 |     5   (0)| 00:00:01 |   KEY |   KEY |  

|*  4 |     INDEX RANGE SCAN                | IND_PART_DT |   450 |       |     3   (0)| 00:00:01 |   KEY |   KEY |  

-------------------------------------------------------------------------------------------------------------------  

  

Predicate Information (identified by operation id):  

---------------------------------------------------  

  

   1 - filter(TO_DATE(:NAME1,'yyyy-mm-dd hh24:mi:ss')<TO_DATE(:NAME2,'yyyy-mm-dd hh24:mi:ss'))  

   4 - access("DT">=TO_DATE(:NAME1,'yyyy-mm-dd hh24:mi:ss') AND "DT"<TO_DATE(:NAME2,'yyyy-mm-dd  

              hh24:mi:ss'))  

以上生成了索引的执行sql  

  

SQL> select /*+FULL(TEST_PART)*/ * from TEST_DBA.TEST_PART where dt>=to_date(:name1,'yyyy-mm-dd hh24:mi:ss') and  

  2  dt<to_date(:name2,'yyyy-mm-dd hh24:mi:ss') ;  

  

        ID STR        DT  

---------- ---------- ---------  

     29155 aaaaaaaaa  21-SEP-12  

     29156 aaaaaaaaa  21-SEP-12  

     29157 aaaaaaaaa  21-SEP-12  

     29158 aaaaaaaaa  21-SEP-12  

     29159 aaaaaaaaa  21-SEP-12  

     29160 aaaaaaaaa  21-SEP-12  

     29161 aaaaaaaaa  21-SEP-12  

     29162 aaaaaaaaa  21-SEP-12  

     29163 aaaaaaaaa  21-SEP-12  

     29164 aaaaaaaaa  21-SEP-12  

  

10 rows selected.  

  

  

Execution Plan  

----------------------------------------------------------  

Plan hash value: 1956636844  

  

-------------------------------------------------------------------------------------------------------  

| Id  | Operation                 | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |  

-------------------------------------------------------------------------------------------------------  

|   0 | SELECT STATEMENT          |           |   250 |  5750 |   161   (3)| 00:00:02 |       |       |  

|*  1 |  FILTER                   |           |       |       |            |          |       |       |  

|   2 |   PARTITION RANGE ITERATOR|           |   250 |  5750 |   161   (3)| 00:00:02 |   KEY |   KEY |  

|*  3 |    TABLE ACCESS FULL      | TEST_PART |   250 |  5750 |   161   (3)| 00:00:02 |   KEY |   KEY |  

-------------------------------------------------------------------------------------------------------  

  

Predicate Information (identified by operation id):  

---------------------------------------------------  

  

   1 - filter(TO_DATE(:NAME1,'yyyy-mm-dd hh24:mi:ss')<TO_DATE(:NAME2,'yyyy-mm-dd hh24:mi:ss'))  

   3 - filter("DT">=TO_DATE(:NAME1,'yyyy-mm-dd hh24:mi:ss') AND  

              "DT"<TO_DATE(:NAME2,'yyyy-mm-dd hh24:mi:ss'))  

以上是走全表扫描的执行计划  

现在要将该语句全部变为走全表扫描,也就是用全表扫描的执行计划来绑定该语句  

SQL> select sql_id from v$sql_plan where plan_hash_value=2229598636;   

  

SQL_ID  

-------------  

day4zwzuhxjnd  

day4zwzuhxjnd  

day4zwzuhxjnd  

day4zwzuhxjnd  

day4zwzuhxjnd  

  

SQL> select sql_id from v$sql_plan where plan_hash_value=1956636844;   

  

SQL_ID  

-------------  

fzs1wktabj9ny  

fzs1wktabj9ny  

fzs1wktabj9ny  

fzs1wktabj9ny  

进行绑定  

SQL> declare  

  2  m_clob clob;  

  3  begin  

  4  select sql_fulltext  

  5  into m_clob  

  6  from v$sql  

  7  where sql_id = 'day4zwzuhxjnd'  

  8  and child_number = 0;  

  9  dbms_output.put_line(m_clob);  

 10  dbms_output.put_line(dbms_spm.load_plans_from_cursor_cache(  

 11  sql_id          => 'fzs1wktabj9ny',  

 12  plan_hash_value => 1956636844,  

 13  sql_text        => m_clob,  

 14  fixed           => 'YES',   

 15  enabled         => 'YES'));  

 16  end;  

 17  /  

PL/SQL procedure successfully completed.  

验证  

SQL> select * from TEST_DBA.TEST_PART where dt>=to_date(:name1,'yyyy-mm-dd hh24:mi:ss') and  

  2  dt<to_date(:name2,'yyyy-mm-dd hh24:mi:ss') ;  

  

        ID STR        DT  

---------- ---------- ---------  

     29155 aaaaaaaaa  21-SEP-12  

     29156 aaaaaaaaa  21-SEP-12  

     29157 aaaaaaaaa  21-SEP-12  

     29158 aaaaaaaaa  21-SEP-12  

     29159 aaaaaaaaa  21-SEP-12  

     29160 aaaaaaaaa  21-SEP-12  

     29161 aaaaaaaaa  21-SEP-12  

     29162 aaaaaaaaa  21-SEP-12  

     29163 aaaaaaaaa  21-SEP-12  

     29164 aaaaaaaaa  21-SEP-12  

  

10 rows selected.  

  

  

Execution Plan  

----------------------------------------------------------  

Plan hash value: 1956636844  

  

-------------------------------------------------------------------------------------------------------  

| Id  | Operation                 | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |  

-------------------------------------------------------------------------------------------------------  

|   0 | SELECT STATEMENT          |           |   250 |  5750 |   161   (3)| 00:00:02 |       |       |  

|*  1 |  FILTER                   |           |       |       |            |          |       |       |  

|   2 |   PARTITION RANGE ITERATOR|           |   250 |  5750 |   161   (3)| 00:00:02 |   KEY |   KEY |  

|*  3 |    TABLE ACCESS FULL      | TEST_PART |   250 |  5750 |   161   (3)| 00:00:02 |   KEY |   KEY |  

-------------------------------------------------------------------------------------------------------  

  

Predicate Information (identified by operation id):  

---------------------------------------------------  

  

   1 - filter(TO_DATE(:NAME1,'yyyy-mm-dd hh24:mi:ss')<TO_DATE(:NAME2,'yyyy-mm-dd hh24:mi:ss'))  

   3 - filter("DT">=TO_DATE(:NAME1,'yyyy-mm-dd hh24:mi:ss') AND  

              "DT"<TO_DATE(:NAME2,'yyyy-mm-dd hh24:mi:ss'))  

  

Note  

-----  

   - SQL plan baseline "SQL_PLAN_c28fvkn3sbtbg70e51298" used for this statement  

  

SQL>   

  

查看生成的sql baseline信息  

SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge    

  2     from dba_sql_plan_baselines where sql_text like '%select * from TEST_DBA.TEST_PART%';  

  

 SIGNATURE SQL_HANDLE                     PLAN_NAME                      ORIGIN         ENA ACC FIX AUT  

---------- ------------------------------ ------------------------------ -------------- --- --- --- ---  

1.3917E+19 SQL_c121db950785e56f           SQL_PLAN_c28fvkn3sbtbg70e51298 MANUAL-LOAD    YES YES YES YES  

  

SQL>   

如果不想要这个绑定计划了,则可以删除它  

declare  

l_pls number;  

begin  

l_pls := DBMS_SPM.DROP_SQL_PLAN_BASELINE(  

sql_handle => 'SQL_c121db950785e56f',  

plan_name  => 'SQL_PLAN_c28fvkn3sbtbg70e51298'  

);  

end;  

对于dbms_spm.load_plans_from_cursor_cache的说明

既然是from cursor的话那么要保证在执行过程中sql还是在内存里的不能被刷出去

declare

m_clob clob;

begin

select sql_fulltext

into m_clob

from v$sql

where sql_id = 'day4zwzuhxjnd'————–原始sql的 sql_id

and child_number = 0;—————–为了让sql只返回一行,也可以rownum=1代替

dbms_output.put_line(m_clob);

dbms_output.put_line(dbms_spm.load_plans_from_cursor_cache(

sql_id          => 'fzs1wktabj9ny',————HINT SQL_ID

plan_hash_value => 1956636844,——————-HINT PLAN_HASH_VALUE

sql_text        => m_clob,————————-原始SQL文本

fixed           => 'YES', ———————禁止演化baseline

enabled         => 'YES'));------生效

end;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: