20.1.1关于游标
一个私有SQL区保存有关解析的SQL语句以及处理其他特定会话的信息。
当服务器进程执行SQL或PL / SQL代码时,该进程使用私有SQL区域存储绑定变量值,查询执行状态信息和查询执行工作区。语句的每次执行的专用SQL区域不共享,并且可以包含不同的值和数据。
一个游标是一个名称或句柄到一个特定的专用SQL区。游标包含特定于会话的状态信息,例如绑定变量值和结果集。
如下图所示,您可以将游标视为客户端上的指针和服务器端上的状态。因为游标与私有SQL区域紧密相关,所以有时可以互换使用这些术语。
图20-1光标
本节包含以下主题:
- 专用和共享SQL区域专用SQL区域中
的光标指向库缓存中的共享SQL区域。 - 父游标和子游标
每个解析的SQL语句都有一个父游标和一个或多个子游标。
20.1.1.1专用和共享SQL区域
专用SQL区域中的光标指向库缓存中的共享SQL区域。
与包含会话状态信息的专用SQL区域不同,共享SQL区域包含语句的解析树和执行计划。例如,的执行SELECT * FROM employees将计划和分析树存储在一个共享的SQL区域中。的执行SELECT * FROM departments在语法和语义上都不同,将计划和分析树存储在单独的共享SQL区域中。
在相同或不同会话中的多个私有SQL区域可以引用单个共享SQL区域,这种现象称为游标共享。例如,SELECT * FROM employees在一个会话中执行和在另一个会话中执行SELECT * FROM employees(访问同一表)可以使用相同的解析树和计划。由多个语句访问的共享SQL区域称为共享游标。
图20-2光标共享
Oracle数据库使用以下步骤自动确定发出的SQL语句或PL / SQL块在文本上是否与库高速缓存中当前存在的另一条语句在文本上相同:
- 该语句的文本被散列。
- 数据库为共享池中的现有SQL语句寻找匹配的哈希值。以下选项是可能的:
- 不存在匹配的哈希值。
在这种情况下,共享池中当前不存在SQL语句,因此数据库将执行硬解析。这将结束共享池检查。
- 存在匹配的哈希值。
在这种情况下,数据库将继续进行下一步,这是文本匹配。
- 不存在匹配的哈希值。
- 数据库将匹配语句的文本与哈希语句的文本进行比较,以确定它们是否相同。以下选项是可能的:
- 文字匹配失败。
在这种情况下,文本匹配过程将停止,从而导致硬解析。
- 文字匹配成功。
在这种情况下,数据库将继续进行下一步:确定SQL是否可以共享现有的父游标。
为了进行文本匹配,SQL语句或PL / SQL块的文本必须以字符为单位,包括空格,大小写和注释。例如,以下语句不能使用相同的共享SQL区域:
SELECT * FROM employees; SELECT * FROM Employees; SELECT * FROM employees;通常,仅文字不同的SQL语句不能使用相同的共享SQL区域。例如,以下语句不会解析到相同的SQL区域:
SELECT count(1) FROM employees WHERE manager_id = 121; SELECT count(1) FROM employees WHERE manager_id = 247;该规则的唯一例外是将参数
CURSOR_SHARING设置为FORCE,在这种情况下,类似的语句可以共享SQL区域。
- 文字匹配失败。
也可以看看:
- “ 父母和孩子的游标 ”
- “ 不要将CURSOR_SHARING = FORCE用作永久修复程序 ”以了解使用过程中涉及的成本
CURSOR_SHARING - Oracle数据库参考,以了解有关
CURSOR_SHARING初始化参数的 更多信息
20.1.1.2父子光标
每个解析的SQL语句都有一个父游标和一个或多个子游标。
父光标存储SQL语句的文本。如果两个语句的文本相同,则这些语句共享相同的父光标。但是,如果文本不同,则数据库将创建一个单独的父游标。
示例20-1父光标
在此示例中,前两个语句在语法上不同(字母“ c”在第一个语句中为小写,在第二个语句中为大写),但在语义上相同。由于语法上的差异,这些语句具有不同的父游标。第三条语句在语法上与第一条语句相同(小写的“ c”),但在语义上有所不同,因为它引用customers了不同模式中的表。由于句法相同,因此第三条语句可以与第一条语句共享一个父游标。
SQL> CONNECT oe@inst1
Enter password: *******
Connected.
SQL> SELECT COUNT(*) FROM customers;
COUNT(*)
----------
319
SQL> SELECT COUNT(*) FROM Customers;
COUNT(*)
----------
319
SQL> CONNECT sh@inst1
Enter password: *******
Connected.
SQL> SELECT COUNT(*) FROM customers;
COUNT(*)
----------
155500
以下查询V$SQL指示两个父母。SQL ID为的语句(即该语句8h916vv2yw400的小写“ c”版本)具有一个父游标和两个子游标:子0和子1。SQLID为的语句5rn2uxjtpz0wd为大写“ c”版本的语句,具有一个不同的父游标和一个子游标:子0。
SQL> CONNECT SYSTEM@inst1
Enter password: *******
Connected.
SQL> COL SQL_TEXT FORMAT a30
SQL> COL CHILD# FORMAT 99999
SQL> COL EXEC FORMAT 9999
SQL> COL SCHEMA FORMAT a6
SQL> SELECT SQL_ID, PARSING_SCHEMA_NAME AS SCHEMA, SQL_TEXT,
2 CHILD_NUMBER AS CHILD#, EXECUTIONS AS EXEC FROM V$SQL
3 WHERE SQL_TEXT LIKE '%ustom%' AND SQL_TEXT NOT LIKE '%SQL_TEXT%' ORDER BY SQL_ID;
SQL_ID SCHEMA SQL_TEXT CHILD# EXEC
------------- ------ ------------------------------ ------ -----
5rn2uxjtpz0wd OE SELECT COUNT(*) FROM Customers 0 1
8h916vv2yw400 OE SELECT COUNT(*) FROM customers 0 1
8h916vv2yw400 SH SELECT COUNT(*) FROM customers 1 1
本节包含以下主题:
- 父游标和V $ SQLAREA
该V$SQLAREA视图为每个父游标包含一行。 - 子游标和V $ SQL
每个父游标都有一个或多个子游标。 - 游标不匹配和V $ SQL_SHARED_CURSOR
如果父游标有多个子游标,则V$SQL_SHARED_CURSOR视图将提供有关为何不共享游标的信息。对于几种不兼容类型,该TRANSLATION_MISMATCH列表示与值Y或不匹配N。
20.1.1.2.1父光标和V$SQLAREA
该V$SQLAREA视图为每个父游标包含一行。
在以下示例中,对的查询V$SQLAREA显示了两个父游标,每个游标都标识有不同的SQL_ID。该VERSION_COUNT指示子游标的数量。
COL SQL_TEXT FORMAT a30
SELECT SQL_TEXT, SQL_ID, VERSION_COUNT, HASH_VALUE
FROM V$SQLAREA
WHERE SQL_TEXT LIKE '%mployee%'
AND SQL_TEXT NOT LIKE '%SQL_TEXT%';
SQL_TEXT SQL_ID VERSION_COUNT HASH_VALUE
------------------------------ ------------- ------------- ----------
SELECT * FROM Employees 5bzhzpaa0wy9m 1 2483976499
SELECT * FROM employees 4959aapufrm1k 2 1961610290在前面的输出中,VERSION_COUNT的2用于SELECT * FROM employees指示多个子游标,因为该声明是针对两个不同的对象执行哪些是必要的。相反,该语句SELECT * FROM Employees(请注意大写字母“ E”)仅执行一次,因此具有一个父游标和一个子游标(VERSION_COUNTof 1)。
20.1.1.2.2子游标和V$SQL
每个父游标都有一个或多个子游标。
一个孩子光标包含的执行计划,绑定变量的元数据查询中所引用的对象,优化环境等信息。与父游标相反,子游标不存储SQL语句的文本。
如果一条语句能够重用父游标,则数据库检查该语句是否可以重用现有的子游标。数据库执行多项检查,包括以下内容:
- 数据库会将发出的语句中引用的对象与池中该语句引用的对象进行比较,以确保它们完全相同。
SQL语句或PL / SQL块中对架构对象的引用必须解析为同一架构中的同一对象。例如,如果两个用户发出以下SQL语句,并且每个用户都有自己的
employees表,则以下语句是不相同的,因为该语句employees为每个用户引用了不同的表:SELECT * FROM employees;注意:
数据库可以共享专用临时表的游标,但只能在同一会话中共享。数据库将会话标识符关联为游标上下文的一部分。在软解析期间,仅当当前会话ID与游标上下文中的会话ID匹配时,数据库才能共享子游标。
- 数据库确定优化器模式是否相同。
例如,必须使用相同的优化器目标来优化SQL语句。
示例20-2多个子光标
V$SQL描述当前驻留在库缓存中的语句。每个子游标都包含一行,如以下示例所示:
SELECT SQL_TEXT, SQL_ID, USERNAME AS USR, CHILD_NUMBER AS CHILD#,
HASH_VALUE, PLAN_HASH_VALUE AS PLAN_HASHV
FROM V$SQL s, DBA_USERS d
WHERE SQL_TEXT LIKE '%mployee%'
AND SQL_TEXT NOT LIKE '%SQL_TEXT%'
AND d.USER_ID = s.PARSING_USER_ID;
SQL_TEXT SQL_ID USR CHILD# HASH_VALUE PLAN_HASHV
----------------------- ------------- --- ------ ---------- ----------
SELECT * FROM Employees 5bzhzpaa0wy9m HR 0 2483976499 1445457117
SELECT * FROM employees 4959aapufrm1k HR 0 1961610290 1445457117
SELECT * FROM employees 4959aapufrm1k SH 1 1961610290 1445457117在前面的结果中,即使相同,CHILD#最下面两个语句的也是不同的(0和1)SQL_ID。这意味着语句具有相同的父游标,但具有不同的子游标。相反,带有SQL_ID 5bzhzpaa0wy9m 的语句, 有一个父级和一个子级(CHILD# 0)。如该PLAN_HASH_VALUE列中的相同值所示,所有三个SQL语句都使用相同的执行计划。
相关话题
20.1.1.2.3游标不匹配和V$SQL_SHARED_CURSOR
如果父游标有多个子游标,则该V$SQL_SHARED_CURSOR视图将提供有关为何不共享游标的信息。对于几种不兼容类型,该TRANSLATION_MISMATCH列表示与值Y或不匹配N。
示例20-3翻译不匹配
在此示例中,该TRANSLATION_MISMATCH列显示两个语句(SELECT * FROM employees)引用了不同的对象,导致最后一个语句的TRANSLATION_MISMATCH值为Y。由于共享是不可能的,每个语句有一个单独的子游标,所指示CHILD_NUMBER的0和1。
SELECT S.SQL_TEXT, S.CHILD_NUMBER, s.CHILD_ADDRESS,
C.TRANSLATION_MISMATCH
FROM V$SQL S, V$SQL_SHARED_CURSOR C
WHERE SQL_TEXT LIKE '%employee%'
AND SQL_TEXT NOT LIKE '%SQL_TEXT%'
AND S.CHILD_ADDRESS = C.CHILD_ADDRESS;
SQL_TEXT CHILD_NUMBER CHILD_ADDRESS T
------------------------------ ------------ ---------------- -
SELECT * FROM employees 0 0000000081EE8690 N
SELECT * FROM employees 1 0000000081F22508 Y



