博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于共享SQL——窥视解析
阅读量:7235 次
发布时间:2019-06-29

本文共 4163 字,大约阅读时间需要 13 分钟。

演员表:

A——————boylook

B——————hr

C——————david


SQL> show user

USER is "BOYLOOK"

SQL> select * from tab;


TNAME TABTYPE CLUSTERID

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

USERENV VIEW

TEST_REFED TABLE

TO_TABLE TABLE

FROM_TABLE TABLE

TEST TABLE


SQL> create table t(x int);


Table created.


SQL> select * from t;


no rows selected


SQL> select * from T;


no rows selected


SQL> create public synonym t for t;


Synonym created.


SQL> grant select on t to david;


Grant succeeded.


SQL> conn hr

Enter password: 

Connected.


SQL> select * from tab;


TNAME TABTYPE CLUSTERID

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

REGIONS TABLE

COUNTRIES TABLE

LOCATIONS TABLE

DEPARTMENTS TABLE

JOBS TABLE

EMPLOYEES TABLE

JOB_HISTORY TABLE

EMP_DETAILS_VIEW VIEW

RLS_TEST TABLE


9 rows selected.


SQL> create table t(x int);


Table created.


SQL> select * from t;


no rows selected


SQL> select * from t;


no rows selected


SQL> conn david

Enter password: 

Connected.


SQL> select * from t;


no rows selected


SQL> conn boylook

Enter password: 

Connected.


让我们看看现在shared_pool里有几条sql呢:
SQL> select address,executions,sql_text from v$sql

2 where upper(sql_text) like 'SELECT * FROM%';


ADDRESS EXECUTIONS

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

SQL_TEXT

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

309D0E74
 
2
←哪两条共享了这句呢?

select * from t


309D0E74 
1

select * from t


308E306C 1

select * from t



ADDRESS EXECUTIONS

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

SQL_TEXT

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

309D0B00 1

select * from T


SQL> show user

USER is "BOYLOOK"

SQL> 
show parameter optimizer_mode


NAME TYPE VALUE

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

optimizer_mode string ALL_ROWS

SQL> 
alter system set optimizer_mode = choose;


System altered.


SQL> 
select * from t;


no rows selected


SQL> select address,executions,sql_text from v$sql

2 where upper(sql_text) like 'SELECT * FROM%';


ADDRESS EXECUTIONS

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

SQL_TEXT

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

309D0E74 2

select * from t


309D0E74 1

select * from t


309D0E74 1

select * from t



ADDRESS EXECUTIONS

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

SQL_TEXT

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

308E306C 1

select * from t


309D0B00 1

select * from T


为了看清楚点,多执行了两次:


SQL> 
select * from t;


no rows selected


SQL> 
select * from t;


no rows selected


OK揭示最终的结果:


SQL> select address,executions,sql_text from v$sql

2 where upper(sql_text) like 'SELECT * FROM%';


ADDRESS EXECUTIONS

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

SQL_TEXT

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

309D0E74 2

select * from t


309D0E74 1

select * from t


309D0E74 
3

select * from t



ADDRESS EXECUTIONS

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

SQL_TEXT

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

308E306C 1

select * from t


309D0B00 1

select * from T

——————————————————————
非常华丽的分割线
——————————————————————————


一句sql从打开游标到最终返回结果或者事务结束需要经历一段漫长的旅途。关于共享SQL,主要发生在解析(parse)阶段。那么在解析的时候是什么样的呢?


首先,检查VPD约束条件(是否有安全策略生成的约束条件,有的话要加到where子句中)。


然后检查语法,语义以及权限:语义指的是引用的对象是否都存在,并且是否用户有权限按照现在的方式访问它们。


这之后,在library cache里面寻找是否存在共享的父游标(将sql散列之后去共享池找相同散列值的sql文本,然后进行比较,以确保sql_text完全一致),如果不存在,就在library cache里分配内存并产生新的父游标。


检查是否存在共享子游标(warning:要获取library cache latch):

检查语义:如果父游标可共享,第一步检查语义:比如上面的A和B都发出了select * from t;但是其实A访问的是A.t,而B访问的是B.t。这样子游标是无法共享的。第二步检查环境:比如优化器的模式,或者pga等。像上面的optimizer_mode从all_rows——>choose,因此虽然A发出了两条select * from t;却无法共享子游标。只有语义和环境等都统一(具体条件可以查询v$sql_shared_cursor),才能共享子游标,直接用执行计划。

如果无法共享子游标,第一步进行逻辑优化(通过各种等价转换,会生成一些列语义上相同的sql);第二步物理优化(对于这一系列的sql生成执行计划,并且根据数据字典的统计信息或者dynamic sampling的信息进行成本cost的计划,选出cost最小的执行计划)。理想上是把一个sql彻底的进行优化,把全部的所有的等价的sql都列出来进行成本计算,可是这样并不现实(执行一句多表的select。。。那是多少排列组合),所以在8i,9i有一个参数来控制生成最大的等价sql集合的大小就是——optimizer_max_permutations。在10g里面是隐藏参数。


这样,就生成了一个子游标,再分配内存(warning:要获取share pool latch),然后插入(释放share pool latch并获取library cache latch)。

然后执行游标,继续接下来的漫长旅行。。。。。。

当父游标和子游标都可以共享的时候,我们称发生了一个软解析(soft parse);否则是硬解析(hard parse)。从性能上来看,硬解析是可怕的。。其实最好是不解析。。这是后话。并且,还有个参数cursor_sharing也影响游标的共享,不过一般都是权宜之计。留给筒子们去思考啦~

本文转自MIKE老毕 51CTO博客,原文链接:http://blog.51cto.com/boylook/1298622,如需转载请自行联系原作者

你可能感兴趣的文章
每天一个linux命令(20):linux chmod命令
查看>>
MySQL复合分区
查看>>
eval解析JSON中的注意点
查看>>
atitit.跨语言实现备份mysql数据库 为sql文件特性 api 兼容性java c#.net php js
查看>>
startActivityForResult不返回结果
查看>>
/dev/null简介
查看>>
uber优步提高成单率,轻松拿奖励!
查看>>
Redis源代码分析(三十五)--- redis.c服务端的实现分析(2)
查看>>
PV(访问量)、UV(独立访客)、IP(独立IP) (转)
查看>>
docker数据拷贝
查看>>
shiro realm 注解失败问题解决过程
查看>>
iOS 静态库,动态库与 Framework 浅析
查看>>
Java对ArrayList进行排序
查看>>
NumberFormat
查看>>
Spring WebSocket初探1 (Spring WebSocket入门教程)<转>
查看>>
winform按钮和子按钮
查看>>
C#回顾 –6.特性
查看>>
Spring和cxf3的整合,以maven的方式
查看>>
Apache Shiro系列三,概述 —— 10分钟入门
查看>>
servlet生命周期
查看>>