性能调优基础3:父游标和子游标
"游标"是用户执行SQL语句时在库缓存中分配的内存区域。该内存区域存储有关SQL语句的关键信息,例如SQL文本、SQL执行计划、统计信息等。
每个SQL语句都有一个父游标和一个或多个子游标。让我们了解一下父游标和子游标是什么。请记住:游标 = 内存区域
为什么有两种不同的光标?
这是Oracle数据库设计的一种机制,它有两种类型的游标:父游标和子游标。对于您执行的每个SQL语句,Oracle引擎将生成两个游标:父游标和子游标。生成两个游标是因为对于同一条SQL语句,可能存在其他差异,比如不同的绑定值、不同的架构或不同的字面值等。父游标将包含SQL语句,而子游标将包含与差异相关的信息。这在本质上使子游标成为决定SQL语句是否进行硬解析或软解析的决定性因素。
父游标
- 它存储游标的 SQL 文本。当两个语句逐字相同时,它们将共享同一个父游标。
- 每个父游标执行时至少会为其创建一个子游标。
- 父游标在视图 V S Q L A R E A 中表示。 v SQLAREA 中表示。v SQLAREA中表示。vsqlarea 中的 VERSION_COUNT 列可以告诉我们这个父游标有多少个子游标。
子游标
- 每个父游标至少有一个子游标,并且也可以有多个子游标。
- 父游标存储 SQL 文本,子游标存储与 SQL 语句相关的其他重要信息,例如:环境详细信息、统计详细信息、绑定变量详细信息、执行计划详细信息、绑定变量详细信息。
- 子游标占用的内存空间较少,因为 SQL 文本未存储在子游标中。
- 每个子游标都必须有一个父游标。
- 子游标决定了查询是进行硬解析还是软解析。你可能会发现这种情况,SQL查询相同的两个语句,父游标是相同的,但子游标不可共享,SQL 会进行硬解析(重新编译)。
- 父游标在视图 V$SQL 中表示。
- V$SQL_SHARED_CURSOR 是一个非常有用的视图,因为它提供了优化器决定将游标标记为非共享的原因。因此,当你看到SQL语句是相同的,但仍然发生了硬解析时,看看这个视图。
V$SQL_SHARED_CURSOR
此视图解释了为什么特定的子游标不与现有的子游标共享的原因,这会导致为同一个父游标创建多个子游标。此视图中的每一列都标识了不能共享游标的特定原因。这些列用“Y”或“N”来描述该值的各种原因。您应该将重点放在值为“Y”的列上。一个特定的子节点共享失败可能有几个原因——例如:一个不同的原因试图使用不同的现有子节点游标。
cursor_sharing数据库参数的概念
由于我们正在讨论父游标和子游标,因此讨论一下cursor_sharing数据库参数是非常重要的。CURSOR_SHARING决定哪种SQL语句可以共享相同的游标。
Cursor_sharing数据库参数可以有三个不同的值:
-
EXACT
只允许具有相同文本的语句共享同一个游标。 -
FORCE
强制在某些字面值上不同但在其他方面相同的语句共享游标,除非字面值影响语句的含义。 -
SIMILAR
使在某些字面值上不同但在其他方面相同的语句共享一个游标,除非字面值影响语句的含义或优化计划的程度。
默认的cursor_sharing值是EXACT,这意味着每个不同的SQL语句都会创建一个新的父游标。下面是两个不同的SQL语句:
select * from EMP WHERE EMP_ID=1;
select * from EMP where EMP_ID=1
这是两个不同的sql,尽管它们都会产生相同的结果。在第一个句子中,where是大写的,而在第二个句子中,where是小写的。
甚至下面的两个语句是两个不同的sql。
select * from EMP where EMP_ID=1;
select * from EMP where EMP_ID=2;
它们是不同的sql,因为字面值(literal values)(1和2)不同。如果cursor_sharing参数为EXACT,执行上述操作将创建两个父游标。
然而,如果将cursor_sharing条件设置为FORCE或SIMILAR,执行上述两个sql将生成一个父游标。当我们这样做时,Oracle会从查询中删除所有字面值,并在优化阶段用绑定变量替换它们。请记住,使用cursor_sharing并不总是有利的。它也会对SQL性能造成不利影响,我们将在以后的文章中讨论。
原文链接: Performance Tuning Basics 3 : Parent and Child Cursors