cursor_sharing
CURSOR_SHARING
| Property | Description |
|---|---|
| Parameter type | String |
| Syntax | CURSOR_SHARING = { EXACT | FORCE } |
| Default value | EXACT |
| Modifiable | ALTER SESSION, ALTER SYSTEM |
| Basic | No |
CURSOR_SHARING determines what kind of SQL statements can share the same cursors.
Values:
FORCEAllows the creation of a new cursor if sharing an existing cursor, or if the cursor plan is not optimal.
EXACTOnly allows statements with identical text to share the same cursor.
Notes:
If you set
CURSOR_SHARING, then Oracle recommends theFORCEsetting unless you are in a DSS environment.The value of the
CURSOR_SHARINGparameter has performance implications. Refer to Oracle Database Performance Tuning Guide before setting this parameter.
cursor_sharing 参数有三个值可选,exact、similar、force。
如果参数值为 exact (Oracle默认方式),当一个 statement parse 的时候,首先到 shared pool 区查看是否有 exact statement 存在(就是看是否在shared pool中有和当前要解析的statement完全一样的语句存在),如果不存在,就执行hard parse;
如果参数值为 similar,那么如果在shared pool中无法找到exact statement的存在的时候,就会在shared pool进行一次新的查找,查找和当前要解析的语句是否是similar statement的语句。(similar statement就是除了value of some literal不同的语句,别的地方都相同的语句。)
当cursor_sharing设置为similar时,如果在shared pool中查找到这样的语句,就会做下一步的检查,看shared pool中缓存的这个语句的execution plan是否适合当前解析的语句,如果适合,就会使用shared pool的语句,而不去做hard parse。如果cursor_sharing设置为force的时候,当在shared pool中发现了similar statement之后,就不会再去检查执行计划了,而直接使用在shared pool的这个语句了。
将cursor_sharing设置为force实际上是危险的。这会可能形成sub optimal的执行计划。比如对于一个范围查找的语句,比如对于一个范围查找的语句,比如
select * from a where a>10 and a<20 这样类型的语句,缓存中的语句的执行计划可能对于正在解析的语句就是不适合的,不是最优的执行计划。
这样看起来是减少了parse恶的时间,但是大大增大了execution的时间。
测试数据:
SQL> select owner,count(*) from t1 group by owner;
OWNER COUNT(*)
------------------------------ ----------
PUBLIC 3360
TEST 1
SYSTEM 527
APPQOSSYS 5
SYS 9440
SQL> create index i_t1_owner on t1(owner);
索引已创建。
SQL> analyze table t1 compute statistics for table for all indexes for all indexed columns;
表已分析。
1、cursor_sharing=exact
SQL> show parameter cursor_sharing
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cursor_sharing string EXACT
SQL> alter system flush shared_pool;
系统已更改。
SQL> select count(*) from t1 where owner='TEST';
COUNT(*)
----------
1
SQL> select count(*) from t1 where owner='SYS';
COUNT(*)
----------
9440 SQL> select sql_text, sql_id, version_count, executions
2 from v$sqlarea
3 where sql_text like 'select count(*) from t1 where owner=%';
SQL_TEXT SQL_ID VERSION_COUNT EXECUTIONS
--------------------------------------------- --------------- ------------- ----------
select count(*) from t1 where owner='SYS' 6n5pk8mynfa7w 1 1
select count(*) from t1 where owner='TEST' 4au4u0sr7kz2p 1 1
v$sqlarea中,version_count是指当前父游标(SQL文本)下的子游标个数,executions指执行次数。
从v$sqlarea的输出可知,字面量不同,会产生两个不同的父游标和子游标,即执行计划不会共享。
从下面执行计划看,这两个SQL产生的执行计划完全不同。
SQL> select * from table(dbms_xplan.display_cursor('6n5pk8mynfa7w',null,null));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID 6n5pk8mynfa7w, child number 0
-------------------------------------
select count(*) from t1 where owner='SYS'
Plan hash value: 1368537905
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 10 (100)| |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
|* 2 | INDEX FAST FULL SCAN| I_T1_OWNER | 9440 | 37760 | 10 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OWNER"='SYS')
已选择19行。
SQL> select * from table(dbms_xplan.display_cursor('4au4u0sr7kz2p',0,''));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID 4au4u0sr7kz2p, child number 0
-------------------------------------
select count(*) from t1 where owner='TEST'
Plan hash value: 923762106
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
|* 2 | INDEX RANGE SCAN| I_T1_OWNER | 1 | 4 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OWNER"='TEST')
已选择19行。
2、cursor_sharing=similar
SQL> alter system flush shared_pool;
系统已更改。
SQL> alter session set cursor_sharing=similar;
会话已更改。
SQL> select count(*) from t1 where owner='TEST';
COUNT(*)
----------
1
SQL> select count(*) from t1 where owner='SYS';
COUNT(*)
----------
9440
SQL> select sql_text, sql_id, version_count, executions
2 from v$sqlarea
3 where sql_text like 'select count(*) from t1 where owner=%';
SQL_TEXT SQL_ID VERSION_COUNT EXECUTIONS
--------------------------------------------- --------------- ------------- ----------
select count(*) from t1 where owner=:"SYS_B_0" gf0m7xnstru5z 2 2
从上面v$sqlarea输出结果可以看出,父游标共享(SQL_ID一样),子游标不同(version_count=2),一共执行两次。
从下面执行计划可以看出,因为子游标不同,虽然sql_id相同,但是仍然产生两个不同的执行计划。
SQL> select * from table(dbms_xplan.display_cursor('gf0m7xnstru5z',null,null));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------
SQL_ID gf0m7xnstru5z, child number 0
-------------------------------------
select count(*) from t1 where owner=:"SYS_B_0"
Plan hash value: 923762106
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
|* 2 | INDEX RANGE SCAN| I_T1_OWNER | 1 | 4 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OWNER"=:SYS_B_0)
SQL_ID gf0m7xnstru5z, child number 1
-------------------------------------
select count(*) from t1 where owner=:"SYS_B_0"
Plan hash value: 1368537905
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 10 (100)| |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
|* 2 | INDEX FAST FULL SCAN| I_T1_OWNER | 9440 | 37760 | 10 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OWNER"=:SYS_B_0)
已选择38行。
3、cursor_sharing=force
SQL> alter system flush shared_pool;
系统已更改。
SQL> alter session set cursor_sharing=force;
会话已更改。
SQL> select count(*) from t1 where owner='TEST';
COUNT(*)
----------
1
SQL> select count(*) from t1 where owner='SYS';
COUNT(*)
----------
9440
SQL> select sql_text, sql_id, version_count, executions
2 from v$sqlarea
3 where sql_text like 'select count(*) from t1 where owner=%';
SQL_TEXT SQL_ID VERSION_COUNT EXECUTIONS
--------------------------------------------- --------------- ------------- ----------
select count(*) from t1 where owner=:"SYS_B_0 gf0m7xnstru5z 1 2
"
从上面v$sqlarea可以看出,父游标共享(sql_id相同),子游标共享(version_count=1),执行两次。
从下面执行计划可以看出,这两个SQL执行计划是一样的,可以认为是第一个SQL共享了第一个SQL的执行计划,也可以认为是绑定变量被窥测了。
其实这样是很危险的,如果第一个传入的值跟传入的第二个值选取的结果差别很大,那么执行效率将会有很大差别。一定要慎用。
SQL> select * from table(dbms_xplan.display_cursor('gf0m7xnstru5z',null,null));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------
SQL_ID gf0m7xnstru5z, child number 0
-------------------------------------
select count(*) from t1 where owner=:"SYS_B_0"
Plan hash value: 923762106
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
|* 2 | INDEX RANGE SCAN| I_T1_OWNER | 1 | 4 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OWNER"=:SYS_B_0)
已选择19行。 cursor_sharing的取值和参数是Oracle library cache中管理生成乃至共享执行计划的重要参数。EXACT值是默认值,实现了直接使用字面SQL不开启转变绑定变量的功能。 而FORCE和SIMILAR取值却开启了字面转绑定变量的功能。在这两个模式下,Oracle会自动的将where后面的条件替换为绑定变量,以增加SQL共享的概率。具体实现sharing的方式上,FORCE和SIMILAR取值又有所差异。 FORCE的sharing原则是共享一切,只生成一个子游标,之后所有都去共享这个子游标的执行计划。随之而来的就是bind peeking问题风险。 而SIMILAR过于谨慎,对每一个SQL都进行类似bind peeking操作。对每个可能取值都生成单独的子游标执行计划。相同的输入共享相同的执行计划。这个虽然避免了bind peeking问题,却带来了新的多version count问题。
cursor_sharing的更多相关文章
- [转]Oracle 初始化参数之cursor_sharing
本文转自:http://www.cnblogs.com/Richardzhu/archive/2013/01/21/2869837.html 一.Cursor_sharing简介: 这个参数是用来告诉 ...
- Oracle cursor_sharing 参数 详解
一. 官网的说明 http://download.oracle.com/docs/cd/E11882_01/server.112/e17110/initparams042.htm#REFRN10025 ...
- ORA 各种oraclesql错误
ORA-00001: 违反唯一约束条件 (.) ORA-00017: 请求会话以设置跟踪事件 ORA-00018: 超出最大会话数 ORA-00019: 超出最大会话许可数 ORA-00020: 超出 ...
- [转载】——故障排除:Shared Pool优化和Library Cache Latch冲突优化 (文档 ID 1523934.1)
原文链接:https://support.oracle.com/epmos/faces/DocumentDisplay?_adf.ctrlstate=23w4l35u5_4&id=152393 ...
- 【转】使用SQL Tuning Advisor STA优化SQL
SQL优化器(SQL Tuning Advisor STA)是Oracle10g中推出的帮助DBA优化工具,它的特点是简单.智能,DBA值需要调用函数就可以给出一个性能很差的语句的优化结果.下面介绍一 ...
- 相克军_Oracle体系_随堂笔记003-体系概述
1.进程结构图 对Oracle生产库来讲,服务器进程(可以简单理解是前台进程)的数量远远大于后台进程.因为一个用户进程对应了一个服务器进程. 而且后台进程一般出问题几率不大,所以学习重点也是服务器进程 ...
- 相克军_Oracle体系_随堂笔记004-shared pool
本章主要阐述SGA中的shared pool. Shared pool { 1.free 2.library cache(缓存sql语句及其执行计划) 3.row cache(数据字典缓存) } ...
- Oracle的优化器介绍
Oracle优化器介绍 本文讲述了Oracle优化器的概念.工作原理和使用方法,兼顾了Oracle8i.9i以及最新的10g三个版本.理解本文将有助于您更好的更有效的进行SQL优化工作. RBO优化器 ...
- Oracle提示大全
Hint概述 基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担.但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比. 此时就需要DBA进行 ...
随机推荐
- iOS中利用 runtime 一键改变字体
1.准备 我们新建一个项目名叫ChangeFont,然后我就随便找了个名叫loveway.ttf的字体库拖进去,里面的工程目录大概就是这样的 目录 现在我们就简单的直接在storyboard上拖了一个 ...
- Android主题切换方案总结
所谓的主题切换,就是能够根据不同的设定,呈现不同风格的界面给用户,也就是所谓的换肤. 1.将主题包(图片与配置)存到SD卡上(可通过下载或手动放入指定目录),在代码里强制从本地文件创建图片与配置文字大 ...
- JDK 动态代理分析
Java的代理有两种:静态代理和动态代理,动态代理又分为 基于jdk的动态代理 和 基于cglib的动态代理 ,两者都是通过动态生成代理类的方法实现的,但是基于jdk的动态代理需要委托类实现接口,基于 ...
- Java并发——线程池Executor框架
线程池 无限制的创建线程 若采用"为每个任务分配一个线程"的方式会存在一些缺陷,尤其是当需要创建大量线程时: 线程生命周期的开销非常高 资源消耗 稳定性 引入线程池 任务是一组逻辑 ...
- verilog 常用系统函数及例子
1.打开文件 integer file_id; file_id = fopen("file_path/file_name"); 2.写入文件:$fmonitor,$fwrite,$ ...
- 程序员带你学习安卓开发系列-Android文件存储
这是程序员带你学习安卓开发系列教程.本文章致力于面向对象程序员可以快速学习开发安卓技术. 上篇文章:.Net程序员快速学习安卓开发-布局和点击事件的写法 主要讲解了布局和点击事件的写法. 上篇文章补充 ...
- (转)我所理解的OOP——UML六种关系
原文地址:http://www.cnblogs.com/dolphinX/p/3296681.html 最近由于经常给公司的小伙伴儿们讲一些OOP的基本东西,每次草纸都被我弄的很尴尬,画来画去自己都乱 ...
- android测试分析1
Android测试框架,开发环境中集成的一部分,提供一个架构和强有力的工具 可以帮助测试你的应用从单元到框架的每个方面. 测试框架有这些主要特征: 1.Android测试组件基于Junit.你可以使用 ...
- .NET笔记系列:LAMBDA表达式常用写法
这里主要是将数据库中的常用操作用LAMBDA表达式重新表示了下,用法不多,但相对较常用,等有时间了还会扩展,并将查询语句及LINQ到时也一并重新整理下: 1.select语句:books.Select ...
- Java分布式缓存框架
http://developer.51cto.com/art/201411/457423.htm 在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓 ...