一个绑定感知游标是一个绑定敏感的游标有资格使用不同的绑定值不同的计划。
在使游标具有绑定意识之后,优化器会根据绑定值及其基数估计来选择将来执行的计划。因此,“绑定感知”实质上是指“当前绑定值的最佳计划”。
当执行带有绑定敏感游标的语句时,优化器将使用内部算法来确定是否标记游标绑定意识。该决定取决于游标对于不同的绑定值是否产生明显不同的数据访问模式,从而导致性能成本与预期不同。
如果数据库将游标标记为可识别绑定,则下次游标执行数据库时,将执行以下操作:
- 根据绑定值生成新计划
- 将为该语句生成的原始光标标记为不可共享(
V$SQL.IS_SHAREABLEisN)。原始游标不再可用,并且有资格在库缓存中过期
当同一查询使用不同的绑定值重复执行时,数据库会将新的绑定值添加到SQL语句的“签名”(包括优化器环境,NLS设置等),并对这些值进行分类。数据库检查绑定值,并考虑当前绑定值是否会导致数据量明显不同,或者现有计划是否足够。数据库并没有需要创建一个新的计划,每一个新的价值。
考虑一种情况,在这种情况下,您将执行一个具有12个不同绑定值的语句(对每个不同值执行两次),这将导致数据库触发5个硬解析,并创建2个其他计划。由于数据库执行5次硬解析,因此即使某些游标与现有游标具有相同的执行计划,它也会创建5个新的子游标。数据库将多余的游标标记为不可用,这意味着这些游标最终会在库高速缓存中过期。
在最初的硬解析期间,优化器实际上是在映射绑定值和适当的执行计划之间的关系。在此初始阶段之后,数据库最终达到稳定状态。使用新的绑定值执行将导致在高速缓存中选择最佳子游标,而无需进行硬解析。因此,解析的数量不会随不同绑定值的数量缩放。
示例20-15绑定感知游标
此示例继续了“ 绑定敏感游标 ”中的示例。以下代码发出第二个查询employees,并将绑定变量设置为50:
EXEC :dept_id := 50;
SELECT COUNT(*), MAX(employee_id) FROM hr.employees WHERE department_id = :dept_id;
COUNT(*) MAX(EMPLOYEE_ID)
---------- ----------------
100045 100999
在前两个执行期间,数据库正在监视查询的行为,并确定不同的绑定值导致查询的基数显着不同。基于此差异,数据库将调整其行为,以使该查询不会始终共享相同的计划。因此,优化器基于当前绑定值生成一个新计划,该值是50:
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID a9upgaqqj7bn5, child number 1
-------------------------------------
SELECT COUNT(*), MAX(employee_id) FROM hr.employees WHERE department_id = :dept_id
Plan hash value: 1756381138
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | |254 (100)| |
| 1 | SORT AGGREGATE | | 1 | 8 | | |
|* 2 | TABLE ACCESS FULL| EMPLOYEES | 100K | 781K |254 (15)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("DEPARTMENT_ID"=:DEPT_ID)
以下查询V$SQL获得有关游标的信息:
SELECT SQL_TEXT, CHILD_NUMBER AS CHILD#, EXECUTIONS AS EXEC,
BUFFER_GETS AS BUFF_GETS, IS_BIND_SENSITIVE AS BIND_SENS,
IS_BIND_AWARE AS BIND_AWARE, IS_SHAREABLE AS SHAREABLE
FROM V$SQL
WHERE SQL_TEXT LIKE '%mployee%'
AND SQL_TEXT NOT LIKE '%SQL_TEXT%';
SQL_TEXT CHILD# EXEC BUFF_GETS BIND_SENS BIND_AWARE SHAREABLE
---------------------- ------ ----- ---------- --------- ---------- ---------
SELECT COUNT(*), MAX(e 0 2 1329 Y N N
mployee_id) FROM hr.em
ployees WHERE departme
nt_id = :dept_id
SELECT COUNT(*), MAX(e 1 1 800 Y Y Y
mployee_id) FROM hr.em
ployees WHERE departme
nt_id = :dept_id
前面的输出显示数据库创建了一个附加的子游标(CHILD#of 1)。光标0现在被标记为不可共享。游标1显示许多缓冲区低于游标0,并被标记为绑定敏感和绑定感知。根据包含绑定变量的谓词的选择性,支持绑定的游标可以对不同的绑定值使用不同的计划。
示例20-16绑定感知游标:选择最佳计划
本示例继续了“ 示例20-15 ”中的示例。以下代码employees以的值执行相同的查询,该查询的10基数极低(仅一行):
EXEC :dept_id := 10;
SELECT COUNT(*), MAX(employee_id) FROM hr.employees WHERE department_id = :dept_id;
COUNT(*) MAX(EMPLOYEE_ID)
---------- ----------------
1 200
以下输出显示优化器基于当前绑定值的低基数估计,选择了最佳计划,即索引扫描10:
SQL> SELECT * from TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID a9upgaqqj7bn5, child number 2
-------------------------------------
select COUNT(*), MAX(employee_id) FROM hr.employees WHERE department_id = :dept_id
Plan hash value: 1642965905
-------------------------------------------------------------------------------------
| Id| Operation | Name |Rows|Bytes|Cost (%CPU)|Time |
-------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | | | |2(100)| |
| 1| SORT AGGREGATE | |1 |8 | | |
| 2| TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES |1 |8 |2 (0)|00:00:01|
|*3| INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 1| |1 (0)|00:00:01|
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("DEPARTMENT_ID"=:DEPT_ID)
在V$SQL现在的输出显示,三个子游标的存在:
SELECT SQL_TEXT, CHILD_NUMBER AS CHILD#, EXECUTIONS AS EXEC,
BUFFER_GETS AS BUFF_GETS, IS_BIND_SENSITIVE AS BIND_SENS,
IS_BIND_AWARE AS BIND_AWARE, IS_SHAREABLE AS SHAREABLE
FROM V$SQL
WHERE SQL_TEXT LIKE '%mployee%'
AND SQL_TEXT NOT LIKE '%SQL_TEXT%';
SQL_TEXT CHILD# EXEC BUFF_GETS BIND_SENS BIND_AWARE SHAREABLE
---------------------- ------ ----- ---------- --------- ---------- ---------
SELECT COUNT(*), MAX(e 0 2 1329 Y N N
mployee_id) FROM hr.em
ployees WHERE departme
nt_id = :dept_id
SELECT COUNT(*), MAX(e 1 1 800 Y Y Y
mployee_id) FROM hr.em
ployees WHERE departme
nt_id = :dept_id
SELECT COUNT(*), MAX(e 2 1 3 Y Y Y
mployee_id) FROM hr.em
ployees WHERE departme
nt_id = :dept_id
当游标切换到绑定感知模式时,数据库将丢弃原始游标(CHILD#of 0)。这是一次性的开销。数据库将游标标记0为不可共享(SHAREABLEis N),这意味着该游标不可用,并且将成为第一个过期的游标缓存之一。




