替换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 ...
随机推荐
- 1.纯 CSS 创作一个按钮文字滑动特效 + 弹幕(残缺)
原文地址:1# 视频演示如何用纯 CSS 创作一个按钮文字滑动特效 扩展后地址:https://scrimba.com/c/cJkzMfd HTML代码: <html> <head& ...
- robot framework添加库注意事项
添加库 假设你的项目结构是这样: 项目 ..myLib(库目录) ..目录1 ..测试用例套件1 此时你需要在“测试用例套件1”中用相对路径添加库myLib,你应该填:../myLib/ 特别注意后面 ...
- HTML5 Canvas 小例子 旋转的图片
<一>CSS部分 @charset "utf-8"; *{ padding:; margin:; outline: none; } #canvas{ position: ...
- css上下或者上中下 自适应布局
方法就是头部不变,中间和底部绝对定位 *{ margin: ; padding: ; } div{ text-align: center; font-size: 30px; } .header,.fo ...
- 创建DataSnap Server
DataSnap REST Application http://edn.embarcadero.com/article/41305 2017.1.19 官方例子 https://community. ...
- 基于OpenGL编写一个简易的2D渲染框架-08 重构渲染器-整体架构
事实上,前面编写的渲染器 Renderer 非常简陋,虽然能够进行一些简单的渲染,但是它并不能满足我们的要求. 当渲染粒子系统时,需要开启混合模式,但渲染其他顶点时却不需要开启混合模式.所以同时渲染粒 ...
- python 2 类与对象
1.类与对象的概念 类即类别.种类,是面向对象设计最重要的概念,从一小节我们得知对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体. 那么问题来了,先有的一个个具体存在的对象(比如一 ...
- event bManualResult
MSDN: bManualReset [in] If this parameter is TRUE, the function creates a manual-reset event object, ...
- 一本很好的书LearnOpenGL
这本书好像不怎么出名,但读起来非常易懂,知识全面 https://learnopengl.com/Advanced-Lighting/Normal-Mapping 基于物理的渲染 – 理论篇 < ...
- Nginx 反向代理、后端检测模块
简介: Nginx 反向代理模块:ngx_http_proxy_module.ngx_http_upstream_module 后端检测模块:nginx_http_upstream_check_mod ...