PL/SQL 静态 SQL 中的游标重用

PL/SQL 静态 SQL 中的游标重用

背景

要执行一条 SQL 语句,就必须对它进行解析(检查语法和语义正确性)并作出执行计划。所有这些都花费计算资源。

为节约这些成本,Oracle 实例为先前遇到的 SQL 语句和合适的导出信息保持了一个全系统范围的 LRU 高速缓存器(aka 共享游标高速缓存器) — 通过 v$sqlarea 访问,因而当提交下一个 SQL 语句进行解析时,将检查它是否与已存储的语句匹配。(匹配标准的定义超出了本教程的范围。粗略地说,当前语句不仅必须与它的匹配对象保持内容上的一致性,其中包括空白和大/小写在内,而且绑定变量的类型也必须匹配。)在当前语句匹配的情况下,将重用存储的导出信息(解析树,执行计划等),从而节约了计算成本。

此外,在游标自身要打开并与待处理的 SQL 语句相联的上下文中也必须进行上述处理,这也需要一些成本。

一个给定的会话可能有一个或几个同时打开的游标。关于这些的信息,包括对 v$sqlarea 的主要外来引用可通过 v$open_cursor 来访问。

高级编程人员使用“困难的”接口来操纵游标 — C 编程环境中的 OCI 或者 PL/SQL 编程环境中的 Dbms_Sql 包 — 一般是代码为显式、相对精巧的方法用来使游标成本减至最小。这种成本节约的范例在下面描述。

对于那些可用 PL/SQL 编程环境中的静态 SQL 来满足需要的程序员,在编写简单的、易于维护的代码时,能享受到隐式执行这种成本节约范例的好处。

然而,粗心的编程可能破坏这些隐式的好处。本教程提供了理解这些内容的概念背景和一些避免错误的指导。

结论

  • 使用 Dbms_Sql 使您得到了基本细化的游标控制等级。它的确允许您运用一些方法,尽可能最大化地重用用来设立游标和对 SQL 语句进行析的资源,甚至当这是软解析时也一样(也就是说该语句在 v$sqlarea 高速缓存器中)。不过,Oracle 一般不推荐用这种方法,因为还有别的更好的方法(参见下面的内容)。

    然而,使用 Dbms_Sql 的确开发了您在该功能的关键领域中的思维模型,所以对它稍作研究和实践至少是有好处的。

  • PL/SQL 中使用显式或隐式游标的静态 SQL 结构都可使您享受到这种成本节约范例所带来的好处,并且不需要对其进行编程。

    因为当 PL/SQL close 语句执行时,或者一条隐式游标语句完成时,PL/SQL 运行系统实际上不关闭您的游标(这是Dbms_Sql.Close_Cursor 动作的结果,aka 硬关闭),所以才使之得以实现。相反地,它仅软关闭您认为已关闭的游标,也就是说它在 PL/SQL 游标高速缓存器(一个潜在可重用开放游标的 LRU 高速缓存器 — 通过 v$open_cursor 访问)中将之标记为今后进行硬关闭的待选游标。

  • 粗心的编程可能破坏此种效果,但通过监控 v$open_cursor 可以方便地诊断和纠正这种错误。
  • 与静态 SQL 一起使用的参考游标目前(直到 Oracle9i)不能为您提供这种节约花费范例的益处。编译人员已对其有所了解,这可能在今后的版本中得到改善。
  • 本地动态 SQL 经常使用由动态字符串打开的参考游标,它没有运用此节约花费范例,原因是它目前在 PL/SQL 中(直到 Oracle9i)的部分没有给出语言结构,一方面来辨别打开和解析,另一方面又辨别绑定、执行和获取。不过,它的性能通常比 Dbms_Sql 好,而且由于这个缘故,它的程序员可用性也更好。在需要动态 SQL 的情况下,建议选择它。
  • 在任何时候都不能将 close 语句遗漏,以便上面给出的任何类型游标结构的 open 语句相平衡。如果您将之遗漏,将产生一个潜在的内存漏洞:这自然是糟糕的代码!不过,PL/SQL 运行时系统一般会为您纠正这种错误。但您不应当依赖于此。

Bryn Llewellyn,PL/SQL 产品经理,Oracle Corp
最新更新时间为 2002 年 2 月 19 日

寄送此页面
Printer View 打印机视图