Oracle 10gR2新SQL提示——opt_param
|
||||||||||||||||
|
||||||||||||||||
Oracle技术站。email: fuyuncat@gmail.com MSN: fuyuncat@hotmail.com ![]() ![]() |
Oracle 10gR2新SQL提示——opt_param
[English]
作者: fuyuncat
来源: www.HelloDBA.com
分享到
我们知道,在Oracle中存在许多参数能够影响SQL的查询计划,如hash_join_enabled、optimizer_index_cost_adj、_optim_peek_user_binds。正确调整这些参数能够解决不少SQL所引起的性能问题。但是,在调整这些参数时需要注意一点,他们是对整个实例其作用的。他们的影响范围如此之大,以至于我们可能通过调整这些参数解决某一条SQL的问题,但是参数的调整却会给其他SQL带来负面影响。有没有办法使某个参数只针对某条语句有一个特殊的数值,而对系统没有影响呢?Oracle 10gR2就提供了一个这样的提示——opt_param。
看下这个提示的用法:/*+opt_param(<parameter_name>[,] <parameter_value>)*/。这个提示的作用就是使我们在某条语句中指定某个系统参数值。
下面看下这个参数是如何起作用的:
SQL> set autot trace
SQL> select t1.object_id, t2.tablespace_name
2 from t_test1 t1, t_test2 t2
3 where t1.object_name = t2.table_name;
2536 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3541962439
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3348 | 170K| 169 (2)| 00:00:03 |
|* 1 | HASH JOIN | | 3348 | 170K| 169 (2)| 00:00:03 |
| 2 | TABLE ACCESS FULL| T_TEST2 | 2072 | 51800 | 17 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T_TEST1 | 47582 | 1254K| 150 (1)| 00:00:02 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."OBJECT_NAME"="T2"."TABLE_NAME")
... ...
SQL> select /*+opt_param('hash_join_enabled', 'false')*/ t1.object_id, t2.tablespace_name
2 from t_test1 t1, t_test2 t2
3 where t1.object_name = t2.table_name;
2536 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 2273132659
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)|Time|
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3348 | 170K| | 840 (1)| 00:
00:11 |
| 1 | MERGE JOIN | | 3348 | 170K| | 840 (1)| 00:
00:11 |
| 2 | SORT JOIN | | 2072 | 51800 | 168K| 34 (3)| 00:
00:01 |
| 3 | TABLE ACCESS FULL| T_TEST2 | 2072 | 51800 | | 17 (0)| 00:
00:01 |
|* 4 | SORT JOIN | | 47582 | 1254K| 3384K| 806 (1)| 00:
00:10 |
| 5 | TABLE ACCESS FULL| T_TEST1 | 47582 | 1254K| | 150 (1)| 00:
00:02 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."OBJECT_NAME"="T2"."TABLE_NAME")
filter("T1"."OBJECT_NAME"="T2"."TABLE_NAME")
... ...
在我们的系统中存在一个案例,就是通过这个提示来解决的。案例的背景描述如下:该系统是一个5*24系统,周末2天是系统维护时间。在系统中存在一个作业,会执行下面一条语句:
SELECT COUNT(A.CARRIER_ID)
FROM CSS_TP_SHMT_QUEUE A,
CSS_TP_SHMT_QUEUE_ACTIVITY B
WHERE A.SHMT_QUEUE_STATUS_CDE = :B3
AND B.SHMT_QUEUE_ID = A.SHMT_QUEUE_ID
AND B.ACTIVITY_STATUS_CDE = :B2
AND A.CARRIER_ID = :B1
AND A.REC_CREAT_DT > SYSDATE - 30
AND ROWNUM <= 1;
我们发现有时这条语句在生产系统上跑的性能非常差,占用单颗CPU100%,运行时间达到几个小时。通过v$sql_plan我们获取到该语句在生产系统上的查询计划如下:
db01> select lpad(' ', 2*(level-1))||operation||' '||options||' '||
2 object_name||' '||decode(id, 0, 'Cost='||cost) "Query Plan_Table"
3 from v$sql_plan
4 start with id = 0
5 and hash_value = 380787837
6 connect by prior id = parent_id
7 and hash_value = 380787837;
Query Plan_Table
------------------------------------------------------------------------------------------------------------
SELECT STATEMENT Cost=3
SORT AGGREGATE
COUNT STOPKEY
NESTED LOOPS
TABLE ACCESS BY INDEX ROWID CSS_TP_SHMT_QUEUE
INDEX UNIQUE SCAN CSS_TP_SHMT_QUEUE_PK
INDEX RANGE SCAN CSS_TP_SHMT_QUEUE_ACTIVITY_IX4
通过分析,这个查询计划是存在问题的,它错误的选择了索引“CSS_TP_SHMT_QUEUE_PK”。我们将相关两张表的统计信息做了更新,但发现这条Top SQL并没有得到改观,还存在生产系统上。
当我们给语句带上参数数值在数据库上进行trace时,却发现它产生了正确的查询计划并在几秒钟之内返回了结果:
db01> SET TIMING ON
db01> SET AUTOT TRACE
db01>
db01> SELECT count(a.carrier_id)
2 FROM css_tp_shmt_queue a, css_tp_shmt_queue_activity b
3 WHERE a.shmt_queue_status_cde = 'E'
4 AND b.shmt_queue_id = a.shmt_queue_id
5 AND b.activity_status_cde = 'EC'
6 AND a.carrier_id = 1
7 AND a.rec_creat_dt > SYSDATE - 30
8 AND rownum <= 1;
Elapsed: 00:00:04.01
Execution Plan
----------------------------------------------------------
Plan hash value: 3859675621
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 19 | 169 (2)| 00:00:03 |
| 1 | SORT AGGREGATE | | 1 | 19 | 150 (1)| 00:00:02 |
| 2 | COUNT STOPKEY | | 1 | 8652 | 169 (2)| 00:00:03 |
| 2 | NESTED LOOPS | | 3348 | 10K| 169 (2)| 00:00:03 |
| 3 | INDEX RANGE SCAN | CSS_TP_SHMT_QUEUE_IDX6 | 234 | 8719 | 17 (0)| 00:00:01 |
| 4 | INDEX RANGE SCAN | CSS_TP_SHMT_QUEUE_ACTIVITY_IX4 | 21 | 134 | 150 (1)| 00:00:02 |
------------------------------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=9 Card=1 Bytes=28)
1 0 SORT (AGGREGATE)
2 1 COUNT (STOPKEY)
3 2 NESTED LOOPS (Cost=9 Card=18465 Bytes=517020)
4 3 INDEX (RANGE SCAN) OF 'CSS_TP_SHMT_QUEUE_IDX6' (NON-
UNIQUE) (Cost=15 Card=18294 Bytes=347586)
5 3 INDEX (RANGE SCAN) OF 'CSS_TP_SHMT_QUEUE_ACTIVITY_IX4' (NON-UNIQUE)
因此,我们初步判断这是由于bind peeking所导致的,因为每周系统维护后,周一会传来一新的数据需要处理,这些数据作为参数传入函数后,根据bind peeking机制,SQL在第一次执行时会根据传入的数据来计算出查询计划。但是由于数据是无法控制的,第一次传入的数据并非典型数据,从而导致优化器采用了不理想的查询计划(关于bind peeking对查询计划的影响,可以参见文章《什么时候使用绑定变量性能反而更差》)。
当然,我们可以通过修改参数“_optim_peek_user_binds”来关闭bind peeking。但是,由于这个参数是实例级,我们无法预知这个参数的修改会对系统其他SQL造成什么影响。轻易改变生产数据库上的任何一个系统参数的DBA是鲁莽的,且后果是不可预知的。我们在这就可以通过使用Oracle提供的这个提示来强制使这条SQL来关闭bind peeking并不会对其他语句产生任何影响:
SELECT /*+opt_param('_optim_peek_user_binds', 'false')*/ COUNT(A.CARRIER_ID)
FROM CSS_TP_SHMT_QUEUE A,
CSS_TP_SHMT_QUEUE_ACTIVITY B
WHERE A.SHMT_QUEUE_STATUS_CDE = :B3
AND B.SHMT_QUEUE_ID = A.SHMT_QUEUE_ID
AND B.ACTIVITY_STATUS_CDE = :B2
AND A.CARRIER_ID = :B1
AND A.REC_CREAT_DT > SYSDATE - 30
AND ROWNUM <= 1;
上一篇:Oracle SCN机制解析 | 下一篇:Oracle IO问题解析(10) |
本类中的所有文章 |
Oracle 10gR2新SQL提示——opt_param的更多相关文章
- oracle 更改SQL提示
在oracle里面修改SQL提示为数据库名称: SQL>set SQLPROMPT "TEST>"
- 解决PL/SQL Dev连接Oracle弹出空白提示框
第一次安装Oracle,装在虚拟机中,用PL/SQL Dev连接远程数据库的时候老是弹出空白提示框,网上找了很久,解决方法也很多,可是就是没法解决我这种情况的. 没办法,只能自己研究,经过大概一天时间 ...
- Oracle 11g 中SQL性能优化新特性之SQL性能分析器(SQLPA)
Oracle11g中,真实应用测试选项(the Real Application Testing Option)提供了一个有用的特点,叫SQL性能分析器(SQL Performance Analyze ...
- PL/SQL Dev连接Oracle弹出空白提示框的解决方法分享
第一次安装Oracle,装在虚拟机中,用PL/SQL Dev连接远程数据库的时候老是弹出空白提示框,网上找了很久,解决方法也很多,可是就是没法解决我这种情况的. 出现这种问题,解决方法大概有这几种: ...
- Oracle 11g 新特性 --SQL Plan Management 说明
Oracle 11g 新特性 --SQL Plan Management 说明 参见大神博主文章: http://blog.csdn.net/tianlesoftware/article/detail ...
- Oracle 10gR2 Dataguard搭建(非duplicate方式)
Oracle 10gR2 Dataguard搭建(非duplicate方式) 我的实验环境: 源生产库(主库): IP地址:192.168.1.30 Oracle 10.2.0.5 单实例 新DG库( ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part3:db安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part3:db安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 5.安装Database软件 5. ...
- Oracle 11g新特性
文章转自网络 Oracle 11g于2007年7月11日美国东部时间11时(北京时间11日22时)正式发布,11g是甲骨文公司30年来发布的最重要的数据库版本,根据用户的需求实现了信息生命周期管理(I ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 1.实施前准备工作 1.1 服务器安装操 ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 3.安装Clus ...
随机推荐
- http-长连接
1. 短链接 http1.0 -- 1个请求-响应过程会创建且1个新的连接 2. 长连接 http1.1 -- 同域下可以创建1个tcp连接,多个请求在同一个tcp上串行处理请求 http2.0 -- ...
- [转帖]【SQL Server】varchar和nvarchar的基本介绍及其区别
https://www.cnblogs.com/zhaoyl9/p/15243556.html varchar(n) 长度为 n 个字节的可变长度且非 Unicode 的字符数据.n 必须是一个介于 ...
- [转帖]Unix Domain Socket– IPC通信机制
什么是Unix Domain Socket 基于socket的框架上发展出一种IPC机制,就是UNIX Domain Socket.虽然网络socket也可用于同一台主机的进程间通讯(通过loopba ...
- [转帖]VMware ESXi 各版本号对照表
本博文转自以下链接: VMware ESXi Release and Build Number History | virten.net vSphere ESXi 7.0 Name Patch Dat ...
- [转帖]crash工具分析Kdump下vmcore文件常用命令总结(三)(实例易懂)
一.简介 本文主要介绍使用crash工具对kdump生成的vmcore文件进行分析,解析常见的crash命令,前面已讲述两章关于Kdump的内容,读者感兴趣可以点击下面的链接: 1.Kdump调试机理 ...
- [转帖]linux下 进程io队列,IO队列和IO调度
IO体系概览 先看看本文主题IO调度和IO队列处于整个IO体系的哪个位置,这个IO体系是非常重要的,了解IO体系我们可以对整个IO过程有个全面的认识.虽然一下两下并不清楚IO体系各个部分的细节,但是我 ...
- [转帖]【JVM】JVM概述
1.JVM定义 JVM 是Java Virtual Machine(JVM )的缩写,Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令进行执行,这样实现了Java"一次编译, ...
- dd命令的简单学习
dd命令简介 dd Copy a file, converting and formatting according to the operands. dd 可以理解为是 disk dump 磁盘转储 ...
- Linux上面批量更新SQLSERVER SQL文本文件的办法
1. 今天同事让帮忙更新几个SQL文件.. 本着自己虽然low 但是不能太low的想法, 简单写一个 shell 脚本来执行. 2. 因为我的linux 里面都安装了 sqlcmd 的工具 所以办法就 ...
- 【DS】【AtCoder】Pakencamp 2022 Day2 H
2023.6.30 Problem Link 有 \(n\) 个帮派在打架,每个帮派有一个大小 \(a_i\),每相邻两个帮派有一个仇恨度 \(b_i\).现在有 \(Q\) 次单点修改 \(a_i\ ...