• 【Oracle优化】通过SQL_PROFILE固化执行计划


    在生产环境中,随着数据量的变化、查询条件的不同,有时执行计划发生了突变而导致SQL性能急剧下降。此时如果调整代码,或者修改业务逻辑,一方面时间上可能来不及,另一方面可能成本较高,那么有没有办法,可以在不调整代码或业务逻辑的情况下,让SQL语句使用计划突变之前的执行计划呢?本篇将介绍通过SQL_PROFILE来固化执行计划的三种方法。

    一 绑定已存在的执行计划

    DECLARE
    
    v_ar_profile_hints sys.sqlprof_attr;
    
    v_clsql_text CLOB;
    
    BEGIN
    
    SELECT extractvalue(VALUE(d), '/hint') AS outline_hints
    
    BULK COLLECT
    
    INTO v_ar_profile_hints
    
    FROM xmltable('/*/outline_data/hint' passing
    
    (SELECT xmltype(other_xml) AS xmlval
    
    FROM dba_hist_sql_plan
    
    WHERE sql_id = 'fzbu6pashquvv'
    
    AND plan_hash_value = '116091679'
    
    AND other_xml IS NOT NULL)) d;
    
    
    
    SELECT sql_text
    
    INTO v_clsql_text
    
    FROM dba_hist_sqltext
    
    WHERE sql_id = 'fzbu6pashquvv';
    
    
    
    dbms_output.put_line(v_clsql_text);
    
    
    
    dbms_sqltune.import_sql_profile(sql_text => v_clsql_text,
    
    profile => v_ar_profile_hints,
    
    NAME => 'test_sql',
    
    force_match => TRUE,
    
    REPLACE => TRUE);
    
    END;

    select * FROM dba_sql_profiles;

    select * FROM v$sql;

    二 手动绑定Outline信息

    1 下面的SQL执行全表扫描;

    2 强制使用索引执行该语句,然后通过v_sqlarea找到其对应的SQL_ID;

    select /*+ index(t IDX_TEST_OWNER)*/ sum(t.object_id) FROM t_test t
    
    where t.owner='PUBLIC';

    3 查看器执行计划

    SELECT *
    
    FROM TABLE(dbms_xplan.display_cursor(sql_id => '8ctw5gjz6z75g',
    
    cursor_child_no => NULL,
    
    format => 'outline'));

    4 绑定Outline

    DECLARE
    
    v_ar_profile_hints sys.sqlprof_attr;
    
    v_clsql_text CLOB;
    
    BEGIN
    
    v_ar_profile_hints := sys.sqlprof_attr('OUTLINE_LEAF(@"SEL$1")',
    
    'INDEX_RS_ASC(@"SEL$1" "T"@"SEL$1" ("T_TEST"."OWNER"))');
    
    SELECT t.sql_text
    
    INTO v_clsql_text
    
    FROM v$sqlarea t
    
    WHERE t.sql_id = 'dtzdyatm69v0f';
    
    dbms_output.put_line(v_clsql_text);
    
    dbms_sqltune.import_sql_profile(sql_text => v_clsql_text,
    
    profile => v_ar_profile_hints,
    
    NAME => 'test_sql',
    
    force_match => TRUE,
    
    REPLACE => TRUE);
    
    END;

    注:需要DBA权限。

    5 查看绑定后的执行计划

    SELECT t.name, t.sql_text, t.status
    
    FROM dba_sql_profiles t
    
    WHERE t.name = 'test_sql';
    
    SELECT t.sql_text, t.sql_id, t.sql_profile
    
    FROM v$sql t
    
    WHERE t.sql_id = 'dtzdyatm69v0f';

    三 借助自动优化任务

    1 查看优化建议

    DECLARE
    
    v_tuning_task VARCHAR2(100);
    
    v_sql_id v$session.prev_sql_id%TYPE := 'dtzdyatm69v0f';
    
    v_task VARCHAR2(30);
    
    
    
    v_report CLOB;
    
    BEGIN
    
    v_task := dbms_sqltune.create_tuning_task(sql_id => v_sql_id);
    
    
    
    dbms_output.put_line('Task is ' || v_task);
    
    v_tuning_task := v_task;
    
    
    
    dbms_sqltune.execute_tuning_task(v_task);
    
    
    
    dbms_output.put_line('Tuning task is ' || v_tuning_task);
    
    
    
    SELECT dbms_sqltune.report_tuning_task(task_name => v_task)
    
    INTO v_report
    
    FROM dual;
    
    dbms_output.put_line('Report is ' || v_report);
    
    END;

    2 接受优化建议

    BEGIN
    
    dbms_sqltune.accept_sql_profile(task_name => v_tuning_task,
    
    REPLACE => TRUE,
    
    force_match => TRUE);
    
    END;
  • 相关阅读:
    分布式事务基本概念
    rocketmq源码分析3-consumer消息获取
    Mac下的Eclipse不能记住工作空间问题
    rocketmq源码分析2-broker的消息接收
    rocketmq源码分析1-benchmark学习
    metrics
    slf4j与logback对接是如何将日志写到控制台的
    Spring AOP
    hibernate数据库连接池,常用配置
    动态代理
  • 原文地址:https://www.cnblogs.com/alen-liu-sz/p/12975608.html
Copyright © 2020-2023  润新知