一尘不染

FETCH / FOR之间的区别以在PL / SQL中循环游标

sql

我知道获取游标将使我能够访问%ROWCOUNT,%ROWTYPE,%FOUND,%NOTFOUND,%ISOPEN等变量

…但是我想知道是否还有其他原因要使用

打开-提取-关闭指令以循环游标

而不是

用FOR循环循环光标…(我认为最好是简单些)

你怎么认为?


阅读 164

收藏
2021-03-17

共1个答案

一尘不染

从性能的角度来看,这种差异比OMG Ponies暗示的Tim Hall技巧要复杂得多。我相信,该技巧是对网上摘录的较大部分的介绍-
我希望蒂姆继续在书中提出大部分(如果不是全部)这些观点。此外,整个讨论取决于您使用的Oracle版本。我相信这对于10.2、11.1和11.2是正确的,但是如果您开始使用旧版本,肯定会有区别。

首先,技巧中的特定示例非常不现实。我从未见过有人使用显式游标而不是SELECT INTO编写单行读取代码。因此,SELECT
INTO更有效的事实在实践中非常有限。如果我们在讨论循环,那么我们感兴趣的性能就是获取许多行的代价。这就是开始出现复杂性的地方。

Oracle在10.1中引入了从游标到PL / SQL集合的大批量数据收集的功能。这是一种将数据从SQL引擎获取到PL /
SQL集合的更为有效的方法,因为它允许您通过一次获取很多行来最大程度地减少上下文移位。这些集合的后续操作效率更高,因为您的代码可以保留在PL /
SQL引擎中。

但是,为了最大程度地利用BULK COLLECT语法,通常必须使用显式游标,因为这样可以填充PL /
SQL集合,然后使用FORALL语法将数据写回到数据库(在合理的假设是,如果您要在游标中获取一堆数据,则很有可能您正在进行某种形式的处理并将所处理的数据保存在某处)。如果您在FOR循环中使用隐式游标(如OMG
Ponies正确指出的那样),Oracle将在幕后进行BULK
COLLECT,以降低数据获取的成本。但是您的代码将进行较慢的逐行插入和更新,因为数据不在集合中。

通常,假设您使用的是10.2或更高版本,并且您的代码正在获取数据并将其写回到数据库,

最快的

  1. 显式游标将BULK COLLECT进行批量收集到本地集合中(具有适当的LIMIT),并使用FORALL写回数据库。
  2. 隐式游标在幕后为您做大量收集,并将单行写回datbase。
  3. 不执行BULK COLLECT且未利用PL / SQL集合的显式游标。

最慢的

另一方面,使用隐式游标可以使您受益于使用批量操作的好处,而无需花费大量的前期费用即可重构旧代码或学习新功能。如果大多数PL /
SQL开发是由主要语言是其他语言或不一定跟上新语言功能的开发人员完成的,则FOR循环将比使用所有语言的显式游标代码更易于理解和维护。新的BULK
COLLECT功能。而且,当Oracle将来推出新的优化方法时,隐式游标代码很可能会自动获得好处,而显式代码则可能需要一些人工返工。

当然,当您要对性能进行故障诊断时,您真正在乎的是循环代码的不同变体可能有多快,这时您通常就在考虑将更多逻辑移入纯SQL的时候。并完全放弃循环代码。

2021-03-17