50

这是基于我面临的面试问题。

很短的定义可以

它可用于操作查询返回的行。

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

4

5 回答 5

61

与大型结果集相比,使用游标就像使用视频流而不是一口气下载视频,并在下载后观看。如果你下载,你必须有几个演出空间和耐心等到下载完成。现在,无论你的机器或网络有多快,每个人看电影的速度都是一样的。

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

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

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

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

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

  • 光标更难做对。考虑一个带有大结果集的查询,促使您使用游标,该游标使用带有聚合函数的 GROUP BY 子句。(这样的查询在数据仓库中很常见)。GROUP BY 可以完全破坏您的服务器,因为它必须一次生成和存储整个结果集,甚至可能在其他表上持有锁。

经验法则:

  • 如果您处理小型、快速创建的结果集,请不要使用游标。
  • 游标擅长于具有大结果集和低一致性要求的即席、复杂(参考)、顺序性质的查询。

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

高温高压

于 2012-04-04T14:20:49.560 回答
31

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

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

说,这个查询:

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

, 对多集a和进行操作b

此查询中的任何内容都不会对记录的顺序、它们的存储方式、访问顺序等做出任何假设。

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

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

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

这正是光标发挥作用的地方。每次在客户端处理结果集时,都在使用游标。您不会从服务器获得兆字节的未排序数据:您只会获得一个小变量:一个结果集描述符,然后编写如下内容:

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

那是为您实现所有这些的游标。

这当然涉及数据库-客户端交互。

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

但是,也有例外:

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

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

于 2010-10-05T12:41:15.443 回答
4

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

有几种情况可能会用到:

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

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

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

于 2010-10-05T12:05:49.970 回答
1

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

于 2012-04-04T14:41:37.533 回答
1

使用游标,您一次访问一行。因此,当您想要处理很多行但在给定时间只有一个时,最好使用它。

我在课堂上被告知,使用游标的原因是您想要访问的行数超过了您的记忆力——因此您不能将所有行都放入一个集合中然后循环遍历它。

于 2010-10-05T07:22:05.030 回答