替换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使用了调整后的执行计划。
替换SQL执行计划的更多相关文章
- Atitit sql执行计划
Atitit sql执行计划 1.1. 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的 Oracle中的执行计划 ...
- 查看SQL执行计划
一用户进入某界面慢得要死,查看SQL执行计划如下(具体SQL语句就不完全公布了,截断的如下): call count cpu elapsed disk ...
- 查看Oracle SQL执行计划的常用方式
在查看SQL执行计划的时候有很多方式 我常用的方式有三种 SQL> explain plan for 2 select * from scott.emp where ename='KING'; ...
- sql执行计划解析案例(二)
sql执行计划解析案例(二) 今天是2013-10-09,本来以前自己在专注oracle sga中buffer cache 以及shared pool知识点的研究.但是在研究cache buffe ...
- Oracle之SQL优化专题01-查看SQL执行计划的方法
在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...
- Oracle中SQL调优(SQL TUNING)之最权威获取SQL执行计划大全
该文档为根据相关资料整理.总结而成,主要讲解Oracle数据库中,获取SQL语句执行计划的最权威.最正确的方法.步骤,此外,还详细说明了每种方法中可选项的意义及使用方法,以方便大家和自己日常工作中查阅 ...
- DB查询分析器7.01新增的周、月SQL执行计划功能
DB查询分析器7.01新增的周.月SQL执行计划功能 马根峰 (广东联合电子服务股份有限公司, 广州 510300) 1 引言 中国本土 ...
- SQL优化 MySQL版 -分析explain SQL执行计划与笛卡尔积
SQL优化 MySQL版 -分析explain SQL执行计划 作者 Stanley 罗昊 [转载请注明出处和署名,谢谢!] 首先我们先创建一个数据库,数据库中分别写三张表来存储数据; course: ...
- 两个左连接SQL执行计划解析(Oracle和PGSQL对比):
上一篇解析链接如下: https://www.cnblogs.com/wcwen1990/p/9325968.html 1.SQL示例1: SQL> select * from ( select ...
随机推荐
- el 表达式的比较和包含
相等( equal ) :eq 不相等( not equal ): ne / neq 大于( greater than ): gt 小于( less than ): lt 大于等于( great th ...
- Procedure-Function oracle
说明:SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML, 数据定义语言DDL,数据控制语言DCL. 0.调试 点击procedure名,右键选择调试.即可进入调试模式.找到procedu ...
- 4 python 类的专有方法介绍
1.__init__ : 构造函数,在生成对象时调用 该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但不一定有返回值. 所谓初始化构造函数就是在构造对象的同时被对象自动 ...
- Css 特性之 transition和transform
CSS 有一些新的属性,可以简化代码的书写,用简单的代码就可以实现复杂的变化.不用像 js 那样,需要写很多代码 这里主要介绍三个属性:transition ,transform,以及translat ...
- 用JDBC如何调用存储过程
package com.huawei.interview.lym; import java.sql.CallableStatement; import java.sql.Connection; imp ...
- maven 的聚合
- Numpy数据存取
Numpy数据存取 numpy提供了便捷的内部文件存取,将数据存为np专用的npy(二进制格式)或npz(压缩打包格式)格式 npy格式以二进制存储数据的,在二进制文件第一行以文本形式保存了数据的元信 ...
- KNN识别手写数字
一.问题描述 手写数字被存储在EXCEL表格中,行表示一个数字的标签和该数字的像素值,有多少行就有多少个样本. 一共42000个样本 二.KNN KNN最邻近规则,主要应用领域是对未知事物的识别,即判 ...
- Ansible 书写我的playbook
mysql 创建数据库 - hosts: localhost remote_user: root tasks: - name: test mysql mysql_db: name: ...
- LPSN获取菌python脚本
本文转载于https://mp.weixin.qq.com/s?__biz=MzIxNzEzODA5NQ==&mid=2649373408&idx=1&sn=232c2cb36 ...