zoukankan      html  css  js  c++  java
  • 替换SQL执行计划

    Switching two different SQL Plan with SQL Profile in Oracle...

    当SQL是业务系统动态生成的,或者是第三方系统产生的,在数据库层面分析发现性能问题时,可能难以实现及时修改业务程序改善执行计划和性能;但可以在数据库层面找到有问题的SQL,调整和改造该SQL,然后将执行计划应用到原始的SQL语句中,步骤如下:

    • 在数据库层面找到性能问题的SQL相关信息;
    • 重构和优化SQL;
    • 对比旧的和优化后的SQL性能信息;
    • 将最优的SQL执行计划应用到原始SQL语句上;

    通过这样的思路,在数据库层面优化SQL性能。来看看下面的示例;

    SQL> @i
    
    USERNAME             INST_NAME            HOST_NAME                 SID   SERIAL#  VERSION    STARTED  SPID       OPID  CPID            SADDR            PADDR
    -------------------- -------------------- ------------------------- ----- -------- ---------- -------- ---------- ----- --------------- ---------------- ----------------
    OPS$SYWU             sydb                 sywu.com                  154   23601    11.2.0.4.0 20160421 23407      25    4144:3660       0000000071E1CC20 0000000072134028
    

    有下面的2个SQL,SQL 1;

    select 
        e.first_name,e.email,e.salary,d.department_name,j.job_title
    from
        employees e,departments d,jobs j
    where
        e.department_id=d.department_id and e.job_id=j.job_id
        and e.salary>8500
    order by
        j.job_title
    ;
    
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                      | Name        | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT               |             |      1 |        |       |    40 (100)|          |     29 |00:00:00.01 |      44 |       |       |          |
    |   1 |  SORT ORDER BY                 |             |      1 |     28 |  2072 |    40   (5)| 00:00:01 |     29 |00:00:00.01 |      44 |  4096 |  4096 | 4096  (0)|
    |*  2 |   HASH JOIN                    |             |      1 |     28 |  2072 |    39   (3)| 00:00:01 |     29 |00:00:00.01 |      44 |   600K|   600K|  802K (0)|
    |   3 |    MERGE JOIN                  |             |      1 |     28 |  1624 |    21   (5)| 00:00:01 |     29 |00:00:00.01 |      23 |       |       |          |
    |   4 |     TABLE ACCESS BY INDEX ROWID| JOBS        |      1 |     19 |   513 |     2   (0)| 00:00:01 |     17 |00:00:00.01 |       2 |       |       |          |
    |   5 |      INDEX FULL SCAN           | JOB_ID_PK   |      1 |     19 |       |     1   (0)| 00:00:01 |     17 |00:00:00.01 |       1 |       |       |          |
    |*  6 |     SORT JOIN                  |             |     17 |     28 |   868 |    19   (6)| 00:00:01 |     29 |00:00:00.01 |      21 |  2048 |  2048 | 2048  (0)|
    |*  7 |      TABLE ACCESS FULL         | EMPLOYEES   |      1 |     28 |   868 |    18   (0)| 00:00:01 |     29 |00:00:00.01 |      21 |       |       |          |
    |   8 |    TABLE ACCESS FULL           | DEPARTMENTS |      1 |     27 |   432 |    18   (0)| 00:00:01 |     27 |00:00:00.01 |      21 |       |       |          |
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------
    

    SQL 1是原始SQL;下面是调整后的SQL 2;

    select /*+ ordered index(d DEPT_ID_PK) index(j JOB_ID_PK) */
       e.first_name,e.email,e.salary,d.department_name,j.job_title
    from
       employees e,departments d,jobs j
    where
       e.department_id=d.department_id and e.job_id=j.job_id
       and e.salary>8500
    order by
       j.job_title
    ;
    
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name              | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                |                   |      1 |        |       |     8 (100)|          |     29 |00:00:00.02 |       6 |      2 |       |       |          |
    |   1 |  SORT ORDER BY                  |                   |      1 |     28 |  2072 |     8  (25)| 00:00:01 |     29 |00:00:00.02 |       6 |      2 |  4096 |  4096 | 4096  (0)|
    |*  2 |   HASH JOIN                     |                   |      1 |     28 |  2072 |     7  (15)| 00:00:01 |     29 |00:00:00.02 |       6 |      2 |   639K|   639K|  881K (0)|
    |   3 |    MERGE JOIN                   |                   |      1 |     28 |  1316 |     5  (20)| 00:00:01 |     29 |00:00:00.02 |       4 |      2 |       |       |          |
    |*  4 |     TABLE ACCESS BY INDEX ROWID | EMPLOYEES         |      1 |     28 |   868 |     2   (0)| 00:00:01 |     29 |00:00:00.01 |       2 |      1 |       |       |          |
    |   5 |      INDEX FULL SCAN            | EMP_DEPARTMENT_IX |      1 |    106 |       |     1   (0)| 00:00:01 |    106 |00:00:00.01 |       1 |      1 |       |       |          |
    |*  6 |     SORT JOIN                   |                   |     29 |     27 |   432 |     3  (34)| 00:00:01 |     29 |00:00:00.01 |       2 |      1 |  2048 |  2048 | 2048  (0)|
    |   7 |      TABLE ACCESS BY INDEX ROWID| DEPARTMENTS       |      1 |     27 |   432 |     2   (0)| 00:00:01 |     27 |00:00:00.01 |       2 |      1 |       |       |          |
    |   8 |       INDEX FULL SCAN           | DEPT_ID_PK        |      1 |     27 |       |     1   (0)| 00:00:01 |     27 |00:00:00.01 |       1 |      1 |       |       |          |
    |   9 |    TABLE ACCESS BY INDEX ROWID  | JOBS              |      1 |     19 |   513 |     2   (0)| 00:00:01 |     19 |00:00:00.01 |       2 |      0 |       |       |          |
    |  10 |     INDEX FULL SCAN             | JOB_ID_PK         |      1 |     19 |       |     1   (0)| 00:00:01 |     19 |00:00:00.01 |       1 |      0 |       |       |          |
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    

    需要做的是在不调整和修改系统代码的情况下使原始的SQL 1使用第二个调整后(SQL 2)的执行计划,so 我们通过创建SQL profile来实现这个目的;

    def v_sqlid='01h5fh3dhccyf'
    
    declare
        l_sql clob; 
    begin
        select t.SQL_FULLTEXT into l_sql from v$sql t where sql_id='&v_sqlid';
        dbms_sqltune.import_sql_profile(sql_text => l_sql,name => 'pro_&v_sqlid',profile => sqlprof_attr('
    IGNORE_OPTIM_EMBEDDED_HINTS
    OPTIMIZER_FEATURES_ENABLE(''11.2.0.4'')
    DB_VERSION(''11.2.0.4'')
    ALL_ROWS
    OUTLINE_LEAF(@"SEL$1")
    INDEX(@"SEL$1" "E"@"SEL$1" ("EMPLOYEES"."DEPARTMENT_ID"))
    INDEX(@"SEL$1" "D"@"SEL$1" ("DEPARTMENTS"."DEPARTMENT_ID"))
    INDEX(@"SEL$1" "J"@"SEL$1" ("JOBS"."JOB_ID"))
    LEADING(@"SEL$1" "E"@"SEL$1" "D"@"SEL$1" "J"@"SEL$1")
    USE_MERGE(@"SEL$1" "D"@"SEL$1")
    USE_HASH(@"SEL$1" "J"@"SEL$1")'
        ));
        dbms_output.put_line('SQL Profile:pro_&v_sqlid imported...');
    end;
    /
    
    SQL Profile:pro_01h5fh3dhccyf imported...
    
    PL/SQL procedure successfully completed.
    

    当重新加载SQL时,执行计划改变,SQL profile被使用;

    select 
        e.first_name,e.email,e.salary,d.department_name,j.job_title
    from
        employees e,departments d,jobs j
    where
        e.department_id=d.department_id and e.job_id=j.job_id
        and e.salary>8500
    order by
        j.job_title
    ;
    
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name              | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                |                   |      1 |        |       |     8 (100)|          |     29 |00:00:00.02 |       6 |      2 |       |       |          |
    |   1 |  SORT ORDER BY                  |                   |      1 |     28 |  2072 |     8  (25)| 00:00:01 |     29 |00:00:00.02 |       6 |      2 |  4096 |  4096 | 4096  (0)|
    |*  2 |   HASH JOIN                     |                   |      1 |     28 |  2072 |     7  (15)| 00:00:01 |     29 |00:00:00.02 |       6 |      2 |   639K|   639K|  869K (0)|
    |   3 |    MERGE JOIN                   |                   |      1 |     28 |  1316 |     5  (20)| 00:00:01 |     29 |00:00:00.01 |       4 |      2 |       |       |          |
    |*  4 |     TABLE ACCESS BY INDEX ROWID | EMPLOYEES         |      1 |     28 |   868 |     2   (0)| 00:00:01 |     29 |00:00:00.01 |       2 |      1 |       |       |          |
    |   5 |      INDEX FULL SCAN            | EMP_DEPARTMENT_IX |      1 |    106 |       |     1   (0)| 00:00:01 |    106 |00:00:00.01 |       1 |      1 |       |       |          |
    |*  6 |     SORT JOIN                   |                   |     29 |     27 |   432 |     3  (34)| 00:00:01 |     29 |00:00:00.01 |       2 |      1 |  2048 |  2048 | 2048  (0)|
    |   7 |      TABLE ACCESS BY INDEX ROWID| DEPARTMENTS       |      1 |     27 |   432 |     2   (0)| 00:00:01 |     27 |00:00:00.01 |       2 |      1 |       |       |          |
    |   8 |       INDEX FULL SCAN           | DEPT_ID_PK        |      1 |     27 |       |     1   (0)| 00:00:01 |     27 |00:00:00.01 |       1 |      1 |       |       |          |
    |   9 |    TABLE ACCESS BY INDEX ROWID  | JOBS              |      1 |     19 |   513 |     2   (0)| 00:00:01 |     19 |00:00:00.01 |       2 |      0 |       |       |          |
    |  10 |     INDEX FULL SCAN             | JOB_ID_PK         |      1 |     19 |       |     1   (0)| 00:00:01 |     19 |00:00:00.01 |       1 |      0 |       |       |          |
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    Note
    -----
       - SQL profile pro_01h5fh3dhccyf used for this statement
    

    原始的SQL使用了调整后的执行计划。

  • 相关阅读:
    51nod_1445 变色DNA 最短路模板 奇妙思维
    51nod_1459 最短路 dijkstra 特调参数
    UVA_10653 公主与王子 #刘汝佳DP题刷完计划
    HOJ 13819 Height map
    51nod_1255字典序最小的子序列
    电梯设计需求调研报告
    梦断代码读后感
    求一循环数组的最大子数组的和
    求二维数组中最大子数组的和
    四则运算
  • 原文地址:https://www.cnblogs.com/lanston/p/switch-two-different-sql-plan.html
Copyright © 2011-2022 走看看