1. v$sql, v$sqlarea, v$sql_shared_cursor
在此之前,我这小菜对于父游标,子游标并不明白,也不明白何时会生成父,子游标, 所以查阅了相关信息,简单总结如下
当用户发出sql语句,oracle会根据该sql的文本信息:sql text生成的hash_value or sql_id(10g)去shared_pool中去寻找是否有相同的sql,如果没有,则为该sql语句生成一个父游标(father cursor)和一个子游标(child cursor).
父游标和v$sqlarea关联, 该视图的每一行表示了一个父游标,其中的version_count这一列表示该父游标含有对应的子游标的个数,父游标包含的信息主要是sql text。
子游标和v$sql关联,该视图的每一行表示了一个子游标,子游标包含的信息主要是该sql语句执行的环境信息,如执行计划等.
如果要共享父子游标,实现软解析,在父游标可以共享,即sql的文本完全相同的情况下,能否实现共享取决于子游标,即sql的执行环境。不能共享(mismatch)的信息可以在v$sql_shared_cursor这个视图中看到,比较常见的情况有:
1. optimizer_mismatch: 即优化器的模式不同,比如设置成all_rows, first_row(n)
2. transaction_mismatch: 事务不同,如不同的用户在相同的其他条件下执行完全相同的sql语句
3. auth_mismatch : 授权不同, 同上
4. bind_mismatch : 绑定变量不同,很典型的情况是变量的长度发生了变化.
哈哈...总结完毕,现在就要开始做一些testing。可惜公司这电脑上我没有DBA权限,下班回去再补上啦..
Let' s continue.. 环境是RHEL5 + oracle 10g
执行以下各条sql语句
SQL> select * from t1 where id = 111;
SQL> select * FROM T1 where id = 111;
SQL> select * from t1 where id = 111;
SQL> select * from t1 where id = 111;
其中第一,三条sql完全相同,与其他两条语句只有空格和大小写的区别。
使用一下语句查看父游标的生成情况
SQL> select sql_id, sql_text, executions, version_count from v$sqlarea where sql_text like '%123';
SQL_ID SQL_TEXT EXECUTIONS VERSION_COUNT
------------- ----------------------------------- ---------- -------------
dkfcapcv90dkz select * FROM T1 where id = 111 1 1
cn5a82qnr4h9d select * from t1 where id = 111 1 1
9mav477ntthkc select * from t1 where id = 111 2 1
注意:
在这里我得到这个结果费尽了几番波折,也体会到了oracle中共享父游标的一些前提条件。首先是执行的sql的文本必须保持完全一致,第二个,cursor_sharing这个初始化参数的设置也很重要,必须为exact,否则oracle会自动的将类似于where id = 111 这样的条件转换为绑定变量的形式. 这样,在v$sqlarea中也无法找到这条刚刚执行的sql,只能在sql中找到类似下列的语句
SQL> select sql_text from v$sql where sql_id = (select prev_sql_id from v$session where sid = sys_context('userenv', 'sid'));
select * from t1 where id = :"SYS_B_0“
这里可以看到oracle强制使用了绑定变量.
而在v$sqlarea中,查找不到相关的sql
通过上面的结果我们可以看到执行的4条sql语句产生了3个父游标,其中的一条共享了已经存在的父游标,因为他们的文本完全一致。
而version_count表示该父游标含有的子游标的个数。关于子游标,就在下一篇里面总结了...
Haha.... Take a show now.