使用数据库游标有什么好处?

时间:2010-10-05 07:17:52

标签: sql database cursor

这是基于我所面对的面试问题。

非常简短的定义可以

  

它可以用来操纵行   由查询返回。

除了使用游标(在MSDN上列出点here)之外,我还有一个问题,如果我们可以使用查询或存储过程执行所有操作(如果我没错,就像我们可以使用Transact-SQL for ms-sql),我们应该使用游标吗?

5 个答案:

答案 0 :(得分:45)

与大型结果集相比,使用游标就像使用视频流而不是一次性下载视频,并在下载时观看它。 如果你下载,你必须有一些空间和耐心等待下载完成。现在,无论您的机器或网络有多快,每个人都以相同的速度观看电影。

通常,在一次活动中,任何查询都会被发送到服务器,执行,结果集通过网络发送给您。 游标将允许您逐行访问数据并仅在您请求时对每一行进行流式处理(实际上可以查看它)。

  • 游标可以节省您的时间 - 因为您无需等待处理和下载完整的记录集
  • 它可以节省您在服务器和客户端上的内存,因为它们不必将大量内存专用于结果集
  • 对网络和服务器进行负载均衡 - 在“突发”模式下工作通常更有效,但它可以完全阻止您的服务器和网络。多用户环境很少需要这种延迟。 Streaming为其他操作留出了空间。
  • 允许对查询表(在某些条件下)上的操作直接影响游标。因此,当您将光标放在行上时,其他进程可以读取,更新甚至删除其他行。这有助于特别是非常繁忙的表,许多并发读写。

然而,这给我们带来了一些警告:

  • 一致性:使用游标,您(通常)不会对数据的一致快照进行操作,而是在一行上进行操作。因此,您的并发/一致性/隔离保证从整个数据库(ACID)只丢失到一行。你通常可以告诉你的DBMS你想要什么级别的并发,但如果你太挑剔了(锁定你所在的完整表),你将丢弃服务器端的许多资源节省。

  • 单独传输每一行可能效率非常低,因为每个数据包都有协商开销,您可以通过每个数据包发送大的,可能是压缩的数据块来避免这种情况。 (没有DB服务器或客户端库是愚蠢到足以单独传输每一行,两端都有缓存和分块,但仍然是相关的。)

  • 游标更难做对。考虑使用大结果集的查询,激励您使用带有聚合函数的GROUP BY子句的游标。 (此类查询在数据仓库中很常见)。 GROUP BY可以完全废弃您的服务器,因为它必须立即生成并存储整个结果集,甚至可能在其他表上持有锁。

经验法则:

  • 如果您处理小型,快速创建的结果集,请不要使用游标。
  • 游标优于临时,复杂(引用),具有大结果集和低一致性要求的顺序性查询。

“顺序性”表示查询中的重型GROUP BY子句中没有聚合函数。服务器可以懒惰地决定为光标计算10行以从缓存中消耗并同时执行其他操作。

HTH

答案 1 :(得分:27)

游标是一种允许您迭代集合中记录的工具。它具有 order 当前记录的概念。

通常,SQL使用多集合进行操作:这些是可能重复记录的集合,没有给定的顺序,作为一个整体。

说,这个查询:

SELECT  *
FROM    a
JOIN    b
ON      b.a = a.id

,对多个问题ab进行操作。

此查询中没有任何内容对记录的顺序,存储方式,访问顺序等做出任何假设,等等。

这允许抽象出实现细节,让系统尝试选择最佳算法来运行此查询。

但是,在转换完所有数据后,最终您需要以有序的方式逐个访问记录。

您不关心电话簿的条目是如何存储在硬盘驱动器上的,但打印机确实要求它们按字母顺序输入;并且格式化标签应该单独应用于每个记录。

这正是光标发挥作用的地方。每次在客户端处理结果集时,都使用游标。你没有从服务器获得兆字节的未排序数据:你只得到一个很小的变量:结果集描述符,只需写下这样的东西:

while (!rs.EOF) {
   process(rs);
   rs.moveNext();
}

这是为你实现所有这一切的光标。

这当然与数据库 - 客户端交互有关。

至于数据库本身:数据库中,你很少需要游标,因为正如我上面所说的,几乎所有的数据转换都可以使用set操作更有效地实现。

然而,也有例外:

    SQL Server中的
  • 分析操作实施得非常糟糕。例如,使用游标可以比使用基于集合的操作
  • 更有效地计算累积和
  • 以块的形式处理数据。有些情况下,应该将基于集合的操作顺序应用于集合的部分,并且每个块的结果应该独立提交。虽然仍然可以使用基于集合的操作来执行此操作,但通常更有一种方法是使用游标。
  • 递归在本机不支持它的系统中。

您也可能会发现这篇文章值得一读:

答案 2 :(得分:3)

使用游标可以通过编程方式顺序读取一组数据,因此其行为方式与传统文件访问类似,而不是SQL的基于集合的行为特征。

有几种情况可能会有用:

  1. 需要模拟基于文件的记录访问行为 - 例如,关系数据库被用作以前编写的一段代码的数据存储机制,以便使用索引文件进行数据存储

  2. 在需要按顺序处理数据的情况下 - 一个简单的示例可能是计算特定客户的运行总余额。 (许多关系数据库,例如Oracle和SQLServer,现在都有SQL的分析扩展,可以大大减少对此的需求。)

  3. 维基百科不可避免地有更多:http://en.wikipedia.org/wiki/Database_cursor

答案 3 :(得分:1)

使用光标,您可以一次访问一行。因此,当你想要操作很多行但在给定时间只有一行时,最好使用它。

我在课堂上被告知,使用光标的原因是你想要访问的行数多于你能够容纳你的内存的数量 - 所以你不能只将所有行放到一个集合中然后遍历它。

答案 4 :(得分:1)

有时基于集合的逻辑会变得相当复杂和不透明。在这些情况下,如果性能不是问题,可以使用服务器端游标将关系逻辑替换为更易于管理和熟悉(对非关系思考者)的过程逻辑,从而使维护更容易。