ITPub博客

首页 > 数据库 > Oracle > v$sql v$sqlarea和父游标 子游标记载01

v$sql v$sqlarea和父游标 子游标记载01

原创 Oracle 作者:dotaddjj 时间:2011-11-22 21:58:31 0 删除 编辑

这个双休去了常州,blog好久没更新了,又偷懒了。今早群里在聊绑定变量,其实对于绑定变量自己也是糊里糊涂的,对于实质的还远远理解不够,pub的老谢给了我们一篇帖子,细细读下去还是受益匪浅啊。

http://www.itpub.net/thread-965919-1-1.html

在oltp事务处理系统中,绑定变量和索引可以说是这个系统中比较重要的两部分,对于索引自己慢慢也有了一定的理解,在索引那些事中自己还是整理了一些心得的。从老谢的帖子中让自己以前的有些错误理解纠正了,记得看杨老大的blog中关于分页查询的分析也让自己恍然大悟,(看过老杨大的物化视图,大师如此认真,后辈们真是太不勤奋了。)对于oracle的学习需要的更多是认真吧!

这里摘要一下老谢的帖子一些信息:

SQL> select * from tt where id=1;

ID NAME
---------- ----------------------------------------
1 test

SQL> select * from tt where id=2;

ID NAME
---------- ----------------------------------------
2 test

SQL> variable i number;
SQL> exec :i :=1;

PL/SQL
过程已成功完成。

SQL> select *from tt where id=:i;

ID NAME
---------- ----------------------------------------
1 test

SQL> exec :i :=2;

PL/SQL
过程已成功完成。

SQL> select *from tt where id=:i;

ID NAME
---------- ----------------------------------------
2 test

SQL> print i;

I
----------
2

SQL> select sql_text,parse_calls from v$sql where sql_text like 'select * from t
t where id=%';

SQL_TEXT PARSE_CALLS
------------------------------------------------------------ -----------
select * from tt where id=2 1
select * from tt where id=1 1
select * from tt where id=:i 2
SQL>
从上面试验发现绑定变量i的使用使查询id=1和id=2的sqlselect *from tt where id=:i得以重复使用,从而避免了hard parse,这里的PARSE_CALLS=2包括了一次soft parse.

从上面可以推翻自己以前记载的静态sql都会使用绑定变量的错误理解。绑定变量的使用跟静态和动态sql没有绝对关系!

这里顺便提一下关于v$sql视图的一些column的含义:

Hash_value: sql语句的hash值,这个hash值用来判断sql语句是否可以共享使用。

Address:sql语句在sga的地址。

Executions: 执行次数

Optimizer_mode:sql执行的优化器模式

Buffer_gets:子指针的buffer gets数量

Disk_reads:子指针disk read的次数

Optimizer_cost:sql执行的cost成本

Hash_value:在library cache父指针的hash value值

End_of_fetch_count:完整执行sql的次数

Loads:对象被装载或重载的次数

Row_processes:sql语句返回的行数

Cpu_time:分析 执行和提取所消耗的时间(微秒)

Elapsed_time:客观上分析 执行 提取所消耗的时间

Sharable_memory:cursor使用的共享内存总数

Persistent_memory:cursor使用的常驻内存总数

Runtime_memory:cursor使用的内存总数

V$sqlarea视图:

V$sqlarea视图和v$sql视图大致结构相同,其中的v$sqlarea有列VERSION_COUNT字段,其中代表的就是对于此父游标的子游标的数量,也就是在v$sql里面的子游标的sql记录的数量。在v$sql中有一列CHILD_NUMBER字段,表示该字游标的编号. v$sqlarea列出了共享SQL区(Shared SQL Area)中的SQL统计信息,这些SQL按照SQL文本的不同,每条会记录一行统计数据。

父游标和子游标有点糊涂了,自己也不能说到很好的表达来描述,还是直接看例子吧!

SQL> alter system flush shared_pool;

System altered

SQL> conn ashuang/ashuang;

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0

Connected as ashuang

SQL> select count(1) from test01;

COUNT(1)

----------

23

SQL> conn test01/test01;

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0

Connected as test

SQL> select count(1) from test01;

COUNT(1)

----------

23

SQL> col sql_text for a40;

SQL> select sql_text,executions,loads,version_count from v$sqlarea where sql_text like '%select count(1) from test01%';

SQL_TEXT EXECUTIONS LOADS VERSION_COUNT

---------------------------------------- ---------- ---------- -------------

select count(1) from test01 1 1 2

select sql_text,executions,loads,versio 1 1 1

n_count from v$sqlarea where sql_text li

ke '%select count(1) from test01%'

SQL> select sql_text,executions,loads,child_number,parsing_schema_name from v$sql where sql_text like '%select count(1) from test01%';

SQL_TEXT EXECUTIONS LOADS CHILD_NUMBER PARSING_SCHEMA_NAME

---------------------------------------- ---------- ---------- ------------ ------------------------------

select count(1) from test01 1 1 0 ASHUANG

select sql_text,executions,loads,versio 1 1 0 TEST

n_count from v$sqlarea where sql_text li

ke '%select count(1) from test01%'

select sql_text,executions,loads,child_ 1 1 0 TEST

number,parsing_schema_name from v$sql wh

ere sql_text like '%select count(1) from

test01%'

在查询过程中虽然sql语句的文本相同,但是实际我们查询的表却是不同的用户,sql的执行计划等都不相同,实际就产生了两个子游标存储相应的sql的执行计划和解析树等。

当一条sql语句出现时,oracle会在库缓存中分配内存,将父游标保存进去,同时v$sqlarea中会记在父游标一条记录,然后如果同一条sql语句出现时,此时如果用户不同或者optimizer_mode不同 绑定量表分级的情况可能导致执行计划不同,从而生成多个子游标。

上面的实验中是用多个用户的来验证子游标的存在,其实在不同的optimizer_mode下同一个用户的同一个sql也会产生多个子游标。

这里就不贴出繁琐的代码了,说下测试的思路:

Select count(1) from test01;

Alter session set optimizer_mode=fistr_rows;

然后再次查询Select count(1) from test01;可以明显的看出会生产两个子游标。

那么父游标与子游标的最终意义了,由于一个sql语句中需要创建游标,然后分析语句运行查询,需要一个游标来指定sql的相关内存地址从而来判断是否能共享sql语句,也就是减小不必要的硬解析啊!

哎准备整理绑定变量的,不知不觉中说到了v$sql和v$sqlarea视图和父子游标去了,后续继续更新!

[@more@]

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25362835/viewspace-1056487/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    220
  • 访问量
    1662989