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使用了调整后的执行计划。

替换SQL执行计划的更多相关文章

  1. Atitit sql执行计划

    Atitit sql执行计划 1.1. 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的 Oracle中的执行计划 ...

  2. 查看SQL执行计划

    一用户进入某界面慢得要死,查看SQL执行计划如下(具体SQL语句就不完全公布了,截断的如下): call     count       cpu    elapsed       disk       ...

  3. 查看Oracle SQL执行计划的常用方式

    在查看SQL执行计划的时候有很多方式 我常用的方式有三种 SQL> explain plan for 2 select * from scott.emp where ename='KING'; ...

  4. sql执行计划解析案例(二)

    sql执行计划解析案例(二)   今天是2013-10-09,本来以前自己在专注oracle sga中buffer cache 以及shared pool知识点的研究.但是在研究cache buffe ...

  5. Oracle之SQL优化专题01-查看SQL执行计划的方法

    在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...

  6. Oracle中SQL调优(SQL TUNING)之最权威获取SQL执行计划大全

    该文档为根据相关资料整理.总结而成,主要讲解Oracle数据库中,获取SQL语句执行计划的最权威.最正确的方法.步骤,此外,还详细说明了每种方法中可选项的意义及使用方法,以方便大家和自己日常工作中查阅 ...

  7. DB查询分析器7.01新增的周、月SQL执行计划功能

                DB查询分析器7.01新增的周.月SQL执行计划功能 马根峰              (广东联合电子服务股份有限公司, 广州 510300) 1      引言   中国本土 ...

  8. SQL优化 MySQL版 -分析explain SQL执行计划与笛卡尔积

    SQL优化 MySQL版 -分析explain SQL执行计划 作者 Stanley 罗昊 [转载请注明出处和署名,谢谢!] 首先我们先创建一个数据库,数据库中分别写三张表来存储数据; course: ...

  9. 两个左连接SQL执行计划解析(Oracle和PGSQL对比):

    上一篇解析链接如下: https://www.cnblogs.com/wcwen1990/p/9325968.html 1.SQL示例1: SQL> select * from ( select ...

随机推荐

  1. centos7.3使用squid搭建代理服务器

    centos7.3使用squid搭建代理服务器 1 安装 yum install squid 2 编辑 vi /etc/squid/squid.conf 3 设置 最底部增加 如下http_acces ...

  2. 多数据源springboot-jta-atomikos

    参考:  https://github.com/classloader/springboot-jta-atomikos-demo 參考:二 :建议参考  https://blog.csdn.net/a ...

  3. 普通web项目转maven项目

    先要有pom.xml文件 1.首先你要确定你的开发工具是否已经安装上maven: 2.安装配置好后将你的项目导入到开发工具上: 3.右键点击java项目,选择maven选项,在选择Enable Dep ...

  4. [ilink32 Error] Error: Unresolved external '__fastcall Data::Win::Adodb::TCustomADODataSet

    [ilink32 Error] Error: Unresolved external '__fastcall Data::Win::Adodb::TCustomADODataSet::GetParam ...

  5. word自动生成章节标题

    一级目录 二级目录 三级标题

  6. ABAP-面向对象的开发

    转载:https://blog.csdn.net/zhongguomao/article/details/70266246 在程序中, 对象的识别和寻址是通过对象引用来实现的,对象引用变量可以访问对象 ...

  7. CSS选择器学习小结

    关于CSS选择器的问题,在实际项目中,以及一般的前端面试中会经常遇到.下面对此做一小结,梳理和巩固相关方面知识.(如有不妥之处,还望大家及时批评指正,以免误导他人) 一.选择器种类 1.id选择器(# ...

  8. jstl遍历list的jsp

    jstl,核心标签库,使用,<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%& ...

  9. 读取数据库信息并生成表设计文档Word版本

    1.参考C#代码 using Help.DBAccessLayer.Business; using Help.DBAccessLayer.Model.SqlGenerator; using Newto ...

  10. HTML的基础知识

    1.什么是HTML? html是一种,用来描述网页的一种语言,指的是一种超文本编辑语言,他不是一种编程的语言,而是一种标记的语言,包含:静态HTML和动态的HTML: 2.学习推荐的网站: http: ...