02 key concept
本章提要
-------------------------------------
术语, 选择性与基数, 软解析与硬解析, 绑定变量, 扩展的游标共享
SQL语句生命周期, 特别关注解析部分
-------------------------------------
选择性和基数
选择性: 操作比例, 比如一个表中有120条记录, 通过条件过滤后, 剩下18条, 选择性就是0.15(18/120)
基数 : 就是一个表中一共的记录, 例如上例中 120
游标的生命周期
打开游标, 系统会在于这个会话相关的服务器进程的服务器端私有内存中为这个游标分配一个内存结构, 也就是用户全局区
UGA, 注意, SQL 语句与游标还没有关联.
解析游标, 有1条SQL语句与这个游标关联, 解析后内容会加载到share pool的library cache中, UGA中的结构会被更新, 以
保存指向这个共享游标在library cache中的位置.
定义输出变量, 如果SQL语句返回数据, 必须先定义接受数据的变量
绑定输入变量, 如果SQL语句使用绑定变量, 必须提供它们的值.
执行游标, 执行这个SQL语句
获取游标, 如果SQL语句返回数据, 这一步接收这些数据.
关闭游标, 释放UGA中的与这个游标有关的资源, 在library cache中的共享游标不会被清除, 以期待被重新使用.
解析过程
1) 包含VPD的约束条件, 安全相关
2) 语法, 语义以及访问权限检查
3) 将父游标保存到library cache中
4) 逻辑优化, 会生成语义等同的新的SQL语句
5) 物理优化, 根据逻辑优化中生成的新的SQL语句产生执行计划, 找到最有效的.
6) 将子游标保存到library cache中
当共享游标与子游标都可用, 对应的解析被称为软解析, 而当所有的操作都需要执行的时候, 被称为硬解析.
共享游标
解析操作的结果是将一个父游标与子游标保存到 library cache中, 很明显, 将它们保存到共享内存区域的目的是为了重用
它们, 从而避免硬解析.
父游标的限制: 父游标 SQL 文本必须完全一致, 才可以被共享. 包括大小写, 空格等.
子游标的限制: (当前执行的SQL), 就是你所处的环境要与父游标一致, 比如, 你修改了参数 optimizer_mode
一般情况下, 是父游标的SQL语句发生变化的情况多, 比如没有使用绑定变量, 至于子游标的环境, 很少.
绑定变量
使用绑定变量, 优点很多, 这里说说缺点,
where 子句中, 会有一些至关重要的信息对查询优化器不可见, 例如 select count(pad) from t where id < 990;
没有使用绑定变量, 在EXPLAIN中, 可以很明显的看到rows是990, 但是, 只要使用绑定变量, 查询优化器都会忽略它们的
具体指. 也可以使用绑定变量窥测技术来实现, 参考如下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
variable id number execute :id := 990; select count(pad) from t where id < :id; -- 这样, 优化器会显示出对应的where条件的值, 此处为990 ------------------------------------------- | Id | Operation | Name | Rows | ------------------------------------------- | 0 | SELECT STATEMENT | | | | 1 | SORT AGGREGATE | | 1 | | 2 | TABLE ACCESS FULL| T | 990 | -------------------------------------------
扩展游标共享
扩展游标共享的目的是 在重用一个已经存在的但是会导致执行效率低下的游标时能够自动进行识别.
通过 v$sql, 11g 以后才有... 以下字段
is_bind_sensitive(绑定是否敏感), 执行计划是否以来窥测到的值, 如果是, 设置Y, 否则设置N
is_bind_aware(是否绑定可知), 如果 Y, 表示这个游标被共享, N, 表示这个游标已经被废弃.
is_shareable(是否可共享), 表明游标是否被共享.
SELECT child_number, is_bind_sensitive, is_bind_aware, is_shareable
FROM v$sql
WHERE sql_id = '7h6n1xkn8trkd'
ORDER BY child_number;
另外, v$sql_cs_statistics, v$sql_cs_selectivity 和 v$sql_cs_histogram 可用来进一步分析.
读写数据块
逻辑读(logical read): 当服务器进程访问到高速缓存(buffer cache)中的一个数据块的时候, 就执行了一次逻辑读.(读写)
物理读(pysical read): 当服务器进程访问高速缓存不存在的数据块时产生一次物理读, 相应的, 它需要打开数据文件,
读这个数据块, 并且将数据块存放到高速缓存中.
物理写(pysical write): 服务器进程不进行物理写, 它们只会在高速缓存中修改数据块, 接着, 数据库写进程dbwr负责
将修改过的数据块(也被称为脏数据块)写到数据文件中
直接读(direct read): 在一些特殊情况下, 服务器进程可以直接从数据文件读取数据块, 数据块不会被加载到高速缓存,
而是直接加载到服务器进程的私有内存中.
直接写(direct write): 在一些特殊情况下, 服务器进程可以直接向数据文件中写入数据块.