暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 试图将SQL_ID 2的执行计划放在SQl_ID 1的基线中

ASKTOM 2019-10-03
378

问题描述


您好Oracle Masters,我需要您的帮助,就像所有人一样 :-)

我正在测试我的数据库基线,我问自己是否有可能将SQL_ID 2的执行计划放在SQl_ID 1的基线中。

这是我的理论测试: 外部软件使用ORDER BY进行选择。我的客户说,我们不需要这个订单,所以把它拿走。供应商说不,六个月前没有补丁。好的,我是DBA,我必须找到解决方案 :-)


我的测试案例: 一张表,有九个人叫马丁,一个叫杜邦。
SQL> CREATE TABLE zztest(id NUMBER(10) CONSTRAINT zztest_pk_id PRIMARY KEY, nom VARCHAR2(50 CHAR), prenom VARCHAR2(50 CHAR) );
Table created.
 
SQL> Begin
      For i in 1..9
      Loop
        INSERT INTO zztest VALUES(i, 'MARTIN', 'TOM'); 
      End loop ;
    End ;
    /
PL/SQL procedure successfully completed.

 
SQL> INSERT INTO zztest VALUES(10, 'DUPONT', 'David'); 
 
SQL> commit;
Commit complete.
 
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname =>'HR', tabname=>'ZZTEST', cascade=>TRUE);


我在没有订单的情况下执行选择: SQL_ID akk1mjcvrdz1q,计划哈希值: 3582063246。
SQL> SELECT * FROM zztest;
        ID NOM               PRENOM                                            
---------- ------------------------------
         1 MARTIN            TOM                                               
         2 MARTIN            TOM                                               
         3 MARTIN            TOM                                               
         4 MARTIN            TOM                                               
         5 MARTIN            TOM                                               
         6 MARTIN            TOM                                               
         7 MARTIN            TOM                                               
         8 MARTIN            TOM                                               
         9 MARTIN            TOM                                               
        10 DUPONT            David                                             
10 rows selected. 
 
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT                                                                                                                                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  akk1mjcvrdz1q, child number 0                                                                                                                                                                   
-------------------------------------                                                                                                                                                                   
SELECT * FROM zztest                                                                                                                                                                                    
 
Plan hash value: 3582063246                                                                                                                                                                             
 
----------------------------------------------------------------------------                                                                                                                            
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                            
----------------------------------------------------------------------------                                                                                                                            
|   0 | SELECT STATEMENT  |        |       |       |     3 (100)|          |                                                                                                                            
|   1 |  TABLE ACCESS FULL| ZZTEST |    10 |   140 |     3   (0)| 00:00:01 |                                                                                                                            
----------------------------------------------------------------------------                                                                                                                            
 
13 rows selected.


现在使用顺序: SQL_ID a1k6qugb0hdz1,计划哈希值: 4012859079。
执行计划不同,还可以,有排序。
SQL> SELECT * FROM zztest ORDER BY nom;
        ID NOM               PRENOM                                            
---------- -------------------------------
        10 DUPONT            David                                             
         2 MARTIN            TOM                                               
         3 MARTIN            TOM                                               
         4 MARTIN            TOM                                               
         6 MARTIN            TOM                                               
         7 MARTIN            TOM                                               
         8 MARTIN            TOM                                               
         9 MARTIN            TOM                                               
         1 MARTIN            TOM                                               
         5 MARTIN            TOM                                               

10 rows selected.

SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT                                                                                                                                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  a1k6qugb0hdz1, child number 0                                                                                                                                                                   
-------------------------------------                                                                                                                                                                   
SELECT * FROM zztest ORDER BY nom                                                                                                                                                                       
 
Plan hash value: 4012859079                                                                                                                                                                             
 
-----------------------------------------------------------------------------                                                                                                                           
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                           
-----------------------------------------------------------------------------                                                                                                                           
|   0 | SELECT STATEMENT   |        |       |       |     4 (100)|          |                                                                                                                           
|   1 |  SORT ORDER BY     |        |    10 |   140 |     4  (25)| 00:00:01 |                                                                                                                           
|   2 |   TABLE ACCESS FULL| ZZTEST |    10 |   140 |     3   (0)| 00:00:01 |                                                                                                                           
-----------------------------------------------------------------------------                                                                                                                           
 
14 rows selected.


现在,我想将计划3582063246与SQL_ID a1k6qugb0hdz1相关联: 一个计划没有排序选择与订单。

为此,我使用order BY为订单创建基线。
SQL> variable cnt number;
SQL> execute :cnt := dbms_spm.load_plans_from_cursor_cache(sql_id => 'a1k6qugb0hdz1');

SQL> select SQL_TEXT, SQL_HANDLE, SIGNATURE, PLAN_NAME, CREATED, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where UPPER(SQL_TEXT) like 'SELECT * FROM ZZTEST%';
SQL_TEXT                                 SQL_HANDLE                SIGNATURE PLAN_NAME              CREATED                       ENA ACC FIX
-------------------------------------------------------------------------------------------------------------------------------- ---------------------------
SELECT * FROM zztest ORDER BY nom        SQL_47464290ab153052      5.1359E+18  SQL_PLAN_4fjk2k2pjac2k192f0eef  28-SEP-19 09.52.12.000000000 AM YES YES NO


现在我想在这个基线中添加SQL_ID akk1mjcvrdz1q的执行计划。
SQL> execute :cnt := dbms_spm.load_plans_from_cursor_cache(sql_handle => 'SQL_47464290ab153052', sql_id => 'akk1mjcvrdz1q', plan_hash_value => '3582063246'); 


哦,问题,基线中只有一个计划,为什么另一个不在这里?我知道共享池中订单的签名和执行计划有匹配,这是为什么它失败了吗?
SQL> select SQL_TEXT, SQL_HANDLE, SIGNATURE, PLAN_NAME, CREATED, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where UPPER(SQL_TEXT) like 'SELECT * FROM ZZTEST%';
SQL_TEXT       SQL_HANDLE      SIGNATURE    PLAN_NAME           CREATED       ENA ACC FIX
--------------------------------------------------------------------------- --- --- ---------------
SELECT * FROM zztest ORDER BY nom SQL_47464290ab153052 5.1359E+18  SQL_PLAN_4fjk2k2pjac2k192f0eef  28-SEP-19 10.42.42.000000 AM YES YES NO



你能告诉我怎么做吗?非常感谢您的回答!

专家解答

My client say, we don't need this ORDER BY, so remove it

他们真的sure关于那个?

大多数没有订单的选择by => 等待发生的错误!

无论如何,我不确定为什么您没有将第二个计划作为基准加载。

“对我有用”:

CREATE TABLE zztest(id NUMBER(10) CONSTRAINT zztest_pk_id PRIMARY KEY, nom VARCHAR2(50 CHAR), prenom VARCHAR2(50 CHAR) );
Begin
  For i in 1..9
  Loop
    INSERT INTO zztest VALUES(i, 'MARTIN', 'TOM'); 
  End loop ;
End ;
/
INSERT INTO zztest VALUES(10, 'DUPONT', 'David'); 
commit;
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname =>user, tabname=>'ZZTEST', cascade=>TRUE);

SELECT * FROM zztest;
SELECT * FROM zztest ORDER BY nom;

variable cnt number;
execute :cnt := dbms_spm.load_plans_from_cursor_cache(sql_id => 'a1k6qugb0hdz1');
select sql_text,
       sql_handle,
       signature,
       plan_name,
       created,
       enabled,
       accepted,
       fixed
from dba_sql_plan_baselines
where upper (sql_text) like 'SELECT * FROM ZZTEST%';

SQL_TEXT                            SQL_HANDLE             SIGNATURE             PLAN_NAME                        CREATED                          ENABLED   ACCEPTED   FIXED   
SELECT * FROM zztest ORDER BY nom    SQL_47464290ab153052       5135865614175645778 SQL_PLAN_4fjk2k2pjac2k192f0eef    03-OCT-2019 10.17.57.000000000    YES        YES         NO       

execute :cnt := dbms_spm.load_plans_from_cursor_cache(sql_handle => 'SQL_47464290ab153052', sql_id => 'akk1mjcvrdz1q', plan_hash_value => '3582063246'); 

select sql_text,
       sql_handle,
       signature,
       plan_name,
       created,
       enabled,
       accepted,
       fixed
from dba_sql_plan_baselines
where upper (sql_text) like 'SELECT * FROM ZZTEST%';

SQL_TEXT                            SQL_HANDLE             SIGNATURE             PLAN_NAME                        CREATED                          ENABLED   ACCEPTED   FIXED   
SELECT * FROM zztest ORDER BY nom    SQL_47464290ab153052       5135865614175645778 SQL_PLAN_4fjk2k2pjac2k192f0eef    03-OCT-2019 10.17.57.000000000    YES        YES         NO       
SELECT * FROM zztest ORDER BY nom    SQL_47464290ab153052       5135865614175645778 SQL_PLAN_4fjk2k2pjac2kb63e4ae3    03-OCT-2019 10.17.57.000000000    YES        YES         NO       


无论如何,这种方法无济于事。没有排序的计划会更改查询的行为。所以数据库不会使用它:

exec :cnt := dbms_spm.drop_sql_plan_baseline('SQL_47464290ab153052','SQL_PLAN_4fjk2k2pjac2k192f0eef');

set serveroutput off

SELECT * FROM zztest ORDER BY nom;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +NOTE'));

PLAN_TABLE_OUTPUT                                         
EXPLAINED SQL STATEMENT:                                   
------------------------                                   
SELECT * FROM zztest ORDER BY nom                          
                                                           
Plan hash value: 4012859079                                
                                                           
-------------------------------------                      
| Id  | Operation          | Name   |                      
-------------------------------------                      
|   0 | SELECT STATEMENT   |        |                      
|   1 |  SORT ORDER BY     |        |                      
|   2 |   TABLE ACCESS FULL| ZZTEST |                      
-------------------------------------                      
                                                           
Note                                                       
-----                                                      
   - Failed to use SQL plan baseline for this statement 


正如注释所说,它不能使用此基线。

如果您必须删除订单 (我会大力推迟),SQL翻译框架将允许您拦截查询并重写它。

https://docs.oracle.com/en/database/oracle/oracle-database/19/drdaa/SQL-translation-framework-overview.html#GUID-C7814DA0-96BA-4D15-A348-6F0960D4475F
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论