And*_*asT 47
与大结果集相比,使用游标就像使用视频流而不是一次性下载视频,并在下载时观看它.如果你下载,你必须有一些空间和耐心等待下载完成.现在,无论您的机器或网络速度有多快,每个人都以相同的速度观看电影.
通常,任何查询都会在一次活动中发送到服务器,执行,并通过网络将结果集发送给您.游标将允许您逐行访问数据,并仅在您请求时对每行进行流式处理(实际上可以查看它).
然而,这给我们带来了一些警告:
一致性:使用游标,您(通常)不会在数据的一致快照上操作,而是在一行上操作.因此,您的并发/一致性/隔离保证从整个数据库(ACID)只丢失到一行.您通常可以告知您的DBMS您想要的并发级别,但如果您太过挑剔(锁定您所在的完整表),您将丢弃服务器端的许多资源节省.
单独传输每一行可能效率非常低,因为每个数据包都有协商开销,您可以通过每个数据包发送大的,可能是压缩的数据块来避免这种情况.(没有DB服务器或客户端库是愚蠢到足以单独传输每一行,两端都有缓存和分块,但仍然是相关的.)
游标更难做对.考虑使用大结果集的查询,激励您使用带有聚合函数的GROUP BY子句的游标.(此类查询在数据仓库中很常见).GROUP BY可以完全废弃您的服务器,因为它必须立即生成并存储整个结果集,甚至可能在其他表上持有锁.
经验法则:
"顺序性"表示查询中的GROUP BY子句中没有聚合函数.服务器可以懒惰地决定为光标计算10行以从缓存中消耗并同时执行其他操作.
HTH
Qua*_*noi 27
游标是一种允许您迭代集合中记录的工具.它有订单和当前记录的概念.
通常,SQL使用多集合进行操作:这些是一组可能重复的记录,没有给定的顺序,作为一个整体.
说,这个查询:
SELECT *
FROM a
JOIN b
ON b.a = a.id
Run Code Online (Sandbox Code Playgroud)
,在multisets a和b.
此查询中的任何内容都不会对记录的顺序,存储方式,访问顺序等进行任何假设.
这允许抽象出实现细节,并让系统尝试选择最佳算法来运行此查询.
但是,在转换完所有数据后,最终需要以有序的方式逐个访问记录.
您不关心电话簿的条目是如何存储在硬盘驱动器上的,但打印机确实要求它们按字母顺序输入; 并且格式化标签应单独应用于每个记录.
这正是游标发挥作用的地方.每次在客户端处理结果集时,都使用游标.您没有从服务器获取兆字节的未排序数据:您只需获得一个小变量:结果集描述符,只需编写如下内容:
while (!rs.EOF) {
process(rs);
rs.moveNext();
}
Run Code Online (Sandbox Code Playgroud)
这是为您实现所有这一切的光标.
这当然涉及数据库 - 客户端交互.
至于数据库本身:在数据库中,你很少需要游标,因为正如我上面所说的,几乎所有的数据转换都可以使用set操作更有效地实现.
但是,也有例外:
SQL Server都很差实施.例如,累积和可以使用游标比使用基于集合的操作更有效地计算您也可能会发现这篇文章值得一读:
使用游标,您可以一次访问一行。因此,当您想要操作大量行但在给定时间只处理一行时,最好使用它。
我在课堂上被告知,使用游标的原因是您想要访问的行数超出了您的内存容量,因此您不能将所有行放入集合中然后循环遍历它。