Oracle 课程九之绑定变量
课程目标
完成本课程的学习后,您应该能够:
子游标 child cursor ---后续运行的SQL 。
父游标的关键信息是SQL语句的文本。
子游标的关键是执行计划和执行环境。
sqlplus test/test
drop table t_cursor purge;
create table t_cursor as select * from dba_objects;
alter system flush shared_pool;
创建实验的表
select count(*) from t_cursor;
select count(*) from T_cursor;
col sql_text format a40;
select sql_id, sql_text, executions from v$sql
where sql_text like '%select count(*) from%_cursor%'
and sql_text not like '%sql_text%';
alter system flush shared_pool;
select sql_id, sql_text, executions from v$sql
where sql_text like '%select count(*) from%_cursor%'
and sql_text not like '%sql_text%';
不共享游标的情况
select count(*) from t_cursor;
select count(*) from t_cursor;
select sql_id, sql_text, executions from v$sql
where sql_text like '%select count(*) from%_cursor%'
and sql_text not like '%sql_text%';
alter system flush shared_pool;
共享游标的情况
--父子游标
alter session set optimizer_mode = all_rows;
select count(*) from t_cursor;
select sql_id, sql_text,child_number,executions from v$sql
where sql_text like '%select count(*) from%_cursor%'
and sql_text not like '%sql_text%';
alter session set optimizer_mode = first_rows_10;
select count(*) from t_cursor;
select sql_id, sql_text,child_number,executions from v$sql
where sql_text like '%select count(*) from%_cursor%'
and sql_text not like '%sql_text%'; grant select any dictionary to scott; sqlplus scott/tiger
drop table t_cursor purge;
create table t_cursor as select * from user_objects;
col sql_text format a40;
select count(*) from t_cursor;
select sql_id, sql_text,child_number, executions from v$sql
where sql_text like '%select count(*) from%_cursor%'
and sql_text not like '%sql_text%';
父子游标
Desc V$SQL_SHARED_CURSOR:
字段意思参考帮助文档:Reference/V$SQL_SHARED_CURSOR
Select * from V$SQL_SHARED_CURSOR;
逻辑优化:这个阶段,通过应用各种不同的转换技巧,会生成语义上等同的新的SQL语句。
物理优化:首先会生成与每个逻辑优化产生的SQL语句有关的执行计划。接着,根据数据字典找到的统计信息或动态取样收集的统计信息,计算出一个与各个执行计划相关的开销。最后,拥有最低开销的执行计划会被选中。
1.3硬解析步骤
1.) 对SQL语句进行语法检查,看是否有语法错误。如果存在语法错误,则退出解析过程;
2.) 通过数据字典(row cache),检查SQL语句中涉及的对象和列是否存在。如果不存在,则退出解析过程;
3.)检查SQL语句的用户是否对涉及到的对象是否有权限。没有则退出解析;
4.)通过优化器创建一个最优的执行计划。这个过程会根据数据字典中的对象的统计信息,来计算多个执行计划的cost,从而得到一个最优的执行计划。
这一步涉及到大量的数据运算,从而会消耗大量的CPU资源;(library cache最主要的目的就是通过软解析来减少这个步骤);
5.)将该游标所产生的执行计划,SQL文本等装载进library cache中的heap中。
1.4软解析、软软解析
软解析: 所谓软解析,就是因为相同文本的SQL语句存在于library cache中,所以本次SQL语句的解析就可以去掉硬解析中的多个步骤。从而节省大量的资源的 耗费。
软软解析:所谓的软软解析,就是没有任何解析过程。当设置了session_cached_cursors参数时,当某个session第三次执行相同的SQL语句时,则会把该SQL语句的游标缓存到PGA中。这样,当该session在执行该SQL语句时,会直接从PGA中取出执行计划,从而跳过解析的所有步骤。
drop table test purge;
alter system flush shared_pool;
create table test as select * from dba_objects where 1<>1;
exec dbms_stats.gather_table_stats(user,'test'); select * from test where object_id=20;
select * from test where object_id=30;
select * from test where object_id=40;
select * from test where object_id=50;
var oid number;
exec :oid:=20;
select * from test where object_id=:oid;
exec :oid:=30;
select * from test where object_id=:oid;
exec :oid:=40;
select * from test where object_id=:oid;
exec :oid:=50;
select * from test where object_id=:oid;
begin
for i in 1..4 loop
execute immediate 'select * from test where object_id=:i' using i;
end loop;
end;
/ select sql_text,s.PARSE_CALLS,loads,executions from v$sql s
where sql_text like 'select * from test where object_id%'
order by 1,2,3,4;
软件解析
2.绑定变量
2.1变量绑定的目的
变量绑定的目的是把硬解析变成软解析:
a.减少SQL硬解析的次数。
b.减少系统资源开销。
c.减少latch争用。
绑定变量也有冬天:bind peeking
bind peeking的由来:在执行含有绑定变量的查询语句时,完成解析和最优化操作之后才能对绑定变量进行绑定,这意味着在实现最优化操作时无法使用绑定变 量列的统计信息。
为了解决这个问题,数据库使用了窥探技术,在第一次解析SQL时,按照窥探变量的值生成执行计划,以后这样的SQL都按照这个执行。
隐藏参数_optim_peek_user_binds=true则启用绑定变量窥探,否则CBO认为统计列是均匀的。
由绑定窥探你想到了什么?
drop table test purge;
create table test as select * from dba_objects;
create index ind_object_id on TEST (object_id);
exec dbms_stats.gather_table_stats(user,'test',cascade=>true);
set autotrace traceonly
select count(object_name) from test where object_id < 10;
select count(object_name) from test where object_id < 1000000;
set autotrace off alter session set statistics_level=all;
alter system flush shared_pool;
var ccc number;
exec :ccc:=10;
select count(object_name) from test where object_id < :ccc;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); exec :ccc:=1000000;
select count(object_name) from test where object_id < :ccc;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); alter system flush shared_pool;
exec :ccc:=1000000;
select count(object_name) from test where object_id < :ccc;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); exec :ccc:=10;
select count(object_name) from test where object_id < :ccc;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
Bind peeking
2.2变量绑定的应用场景
OLTP环境应该使用绑定变量:
---OLTP环境模拟
drop table t purge;
create table t (name varchar2(20),department_id number(10)); begin
for i in 1 .. 10000 loop
insert into t values ('test'||i,i);
end loop;
commit;
end;
/
select * from t;
------------以上为创造实验环境--------------
---如果我们要将test1、test2两个用户转部门,那么产生的sql应该是以下两条内容
select department_id from t where name = 'test1'
update t set department_id=1000 where name ='test1';
commit; select department_id from t where name = 'test2'
update t set department_id=1000 where name ='test2';
commit;
---如果使用绑定变量,那么sql应该是以下内容
select department_id from t where name = :x;
update t set department_id=1000 where name =:x;
---通过绑定变量,我们将两次硬解析变成了一次硬解析 ---接下来我们看绑定变量与不绑定变量的性能区别
alter session set tracefile_identifier = 'Look_For_Me';
alter session set events '10046 trace name context forever,level 12'; begin ---不绑定
for x in 1..10000 loop
execute immediate 'select * from t where name ='||x;
end loop;
end;
/ begin ---绑定
for x in 1..10000 loop
execute immediate 'select * from t where name =:x' using x;
end loop;
end;
/ alter session set events '10046 trace name context off';
绑定变量应用举例
OLAP环境不应该使用绑定变量:
OLAP环境大多时候是报表处理,操作的结果集庞大,并且数据往往不均匀,在这种情况下,谓词条件不同,获取到的数据量也不一定相同,执行计划就不一定相同,这个时候,变量就不那么合适了
在OLAP系统中,根据不同谓词条件选择不同的执行计划是至关重要的,这时候,解析的代价和大查询的代价比较起来,sql解析消耗的资源是可以忽略不计的
用户量较少、执行次数少。
2.3游标共享(cursor_sharing)
cursor sharing用来告诉oracle什么情况下可以共享游标,即SQL重用。oracle默认cursor_sharing 是exact 指的是SQL语句必须绝对一样的情况下才能共享游标,否则作为新的SQL语句处理。
适合场景:使用exact 高效的前提是应用代码中使用了绑定变量,这也是oracle推荐的。
Drop table t purge;
show parameter cursor_sharing;
create table t as select * from dba_objects;
alter system flush shared_pool;
select /*+test_exact*/count(1) from t where object_id=100;
select /*+test_exact*/count(1) from t where object_id=200;
col sql_text format a80;
select sql_text from v$sql where sql_text like '%/*+test_exact*/%'
and sql_text not like '%sql_text%'; alter system flush shared_pool;
var x number;
exec :x:=100;
select /*+test_exact*/count(1) from t where object_id=:x;
exec :x:=200;
select /*+test_exact*/count(1) from t where object_id=:x;
select sql_text from v$sql where sql_text like '%/*+test_exact*/%'
and sql_text not like '%sql_text%';
游标共享
cursor sharing=force,oracle将2条类似的SQL的谓词用一个变量代替,同时将它们看做同一条SQL语句处理
适用场景:在无法将应用的代码修改为绑定变量情况下,oracle提供的一种解决方法。
注意:游标共享特性有个不太好的名声,就是它不是很稳定,过去数年,大量与之相关的bug被发现和确认。
Drop table t purge;
show parameter cursor_sharing;
create table t as select * from dba_objects;
alter session set cursor_sharing=force;
alter system flush shared_pool;
select /*+test_force*/count(1) from t where object_id=100;
select /*+test_force*/count(1) from t where object_id=100;
select /*+test_force*/count(1) from t where object_id=200;
col sql_text format a80;
select sql_id,child_number,sql_text from v$sql where sql_text like '%/*+test_force*/%'
and sql_text not like '%sql_text%'
And sql_text not like '%EXPLAIN PLAN%';
游标共享2
cursor_sharing=similar ,exact和force折中的参数。当探测到谓词会导致执行计划的改变,就会重新解析,否则不会。
适用场景:在无法将应用的代码修改为绑定变量情况下,oracle提供的又一种解决方法,similar的好处是最大限度地避免CBO在绑定变量的情况下做出的错误的判断,但它的代价是分析的次数变大。
Drop table t purge;
show parameter cursor_sharing;
create table t as select * from dba_objects;
Create index ind_t_object_id on t(object_id) nologging;
exec dbms_stats.gather_table_stats(user,'t',cascade => true);
alter session set cursor_sharing=similar;
Set autotrace traceonly
select /*+test_similar*/* from t where object_id<10;
select /*+test_similar*/* from t where object_id<100000;
Set autotrace off alter system flush shared_pool;
Set autotrace traceonly
select /*+test_similar*/* from t where object_id<10;
select /*+test_similar*/* from t where object_id<100000;
Set autotrace off
col sql_text format a80;
select sql_id,child_number,sql_text from v$sql where sql_text like '%/*+test_similar*/%'
and sql_text not like '%sql_text%'
And sql_text not like '%EXPLAIN PLAN%'; alter system flush shared_pool;
Set autotrace traceonly
select /*+test_similar*/* from t where object_name='aaa';
select /*+test_similar*/* from t where object_name='bbb';
select /*+test_similar*/* from t where object_name='ccc';
select /*+test_similar*/* from t where object_name='ddd';
Set autotrace off
select sql_id,child_number,sql_text from v$sql where sql_text like '%/*+test_similar*/%'
and sql_text not like '%sql_text%'
And sql_text not like '%EXPLAIN PLAN%';
游标共享3
Oracle 课程九之绑定变量的更多相关文章
- Oracle实用-01:绑定变量
数据库虽然在学校系统学习过,但是在工作中真正使用起来收获又是不一样的,今天起打算将项目中使用到的技术再分享出来,不以书本的顺序,只从碰到的问题为顺序. 虽然不是纯粹的数据库工程师,但是每个程序员总免不 ...
- ORACLE 根据 sql_id 查询绑定变量的传入值
查询当前查询: select b.NAME,b.POSITION,b.DATATYPE_STRING,b.VALUE_STRING,b.LAST_CAPTUREDfrom v$sql_bind_cap ...
- ORACLE 根据sql_id查询绑定变量的传入值
当前查询: select b.NAME, b.POSITION, b.DATATYPE_STRING, b.VALUE_STRING, b.LAST_CAPTURED from v$sql_bind_ ...
- Oracle绑定变量
select * from table where id = ? 类似于上面这样的sql,如果不用绑定变量,每次执行时Oracle会认为是不同的sql,会在每次执行时生成一遍执行计划,而执行计划的生成 ...
- PostgreSQL 绑定变量窥探
今天我们要探讨的是 custom执行计划和通用执行计划.这一技术在 Oracle中被称为绑定变量窥视.但 Kingbase中并没有这样的定义,更严格地说,Kingbase叫做custom执行计划和通用 ...
- [转]ORACLE 绑定变量用法总结
转:http://blog.csdn.net/wanghai__/article/details/4778343 在oracle 中,对于一个提交的sql语句,存在两种可选的解析过程, 一种叫做硬解析 ...
- ORACLE 绑定变量用法总结 .
之前对ORACLE中的变量一直没个太清楚的认识,比如说使用:.&.&&.DEIFINE.VARIABLE……等等.今天正好闲下来,上网搜了搜相关的文章,汇总了一下,贴在这里,方 ...
- Oracle --获取绑定变量的值.
SELECT * FROM DBA_HIST_SQLBIND WHERE SNAP_ID>67073 AND SNAP_ID<=67079 AND SQL_ID='3DR3410F086P ...
- oracle 绑定变量
“绑定变量”这个词也许对于某些人来说看以来陌生,其实我们在很早的时候就已经开始运用它了. 在java中使用的PrepareStatement对象,大家一定会说这不是将sql语句做预编译操作嘛,被封装的 ...
随机推荐
- 想知道吗?CTO 比普通程序员强在哪?
互联网的蓬勃发展,让无数的程序员身价水涨船高,都变成了「香饽饽」,更有了不少「创业」,「当上 CTO,迎娶白富美的传说」.都说不想当元帅的士兵不是好士兵,我觉得这件事见仁见智,但提升自己的价值,让自己 ...
- java基础知识回顾之java Thread类--java线程实现常见的两种方式实现Runnable接口(二)
创建线程的第二中方式: /** * 步骤: 1定义类实现Runnable接口 2.实现Runnable接口中的run方法. 3.通过Thread类建立线程对象,并将Run ...
- Selenium WebDriver 中鼠标和键盘事件分析及扩展(转)
本文将总结 Selenium WebDriver 中的一些鼠标和键盘事件的使用,以及组合键的使用,并且将介绍 WebDriver 中没有实现的键盘事件(Keys 枚举中没有列举的按键)的扩展.举例说明 ...
- 包含中文的字符串中截取前N个字符
package com.wangzhu.string; import java.io.UnsupportedEncodingException; public class SubStringDemo1 ...
- lintcode:anagrams 乱序字符串
题目 乱序字符串 给出一个字符串数组S,找到其中所有的乱序字符串(Anagram).如果一个字符串是乱序字符串,那么他存在一个字母集合相同,但顺序不同的字符串也在S中. 您在真实的面试中是否遇到过这个 ...
- Project Euler 78:Coin partitions
Coin partitions Let p(n) represent the number of different ways in which n coins can be separated in ...
- [@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam
[@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam 转载:http://blog ...
- AndroidManifest.xml介绍一
下面是AndroidManifest.xml的简单介绍,直接上图! 一.manifest结点的属性介绍 二.application结点属性介绍 三.activity.intent-filter.use ...
- iOS Container View Controller
一.UIViewController 做iOS开发的经常会和UIViewController打交道,从类名可知UIViewController属于MVC模型中的C(Controller),说的更具体点 ...
- WPF中Timer与DispatcherTimer类的区别
前几天在WPF中写了一个轨迹回放的功能,我想稍微做过类似项目的,都晓得采用一个时间控件或者时间对象作为调度器,我在这么做的时候,出现了问题,于是将程序中的Timer换成了DispatchTimer,然 ...