当前位置:  开发笔记 > 编程语言 > 正文

为什么人们如此讨厌SQL游标?

如何解决《为什么人们如此讨厌SQL游标?》经验,为你挑选了8个好方法。

我可以理解为了避免因为开销和不便而不得不使用光标,但看起来有一些严重的光标 - 恐惧症 - 狂热正在进行,人们将不遗余力地避免使用光标.

例如,有一个问题询问如何使用游标执行明显无关紧要的操作,并使用带有递归自定义函数的公用表表达式(CTE)递归查询提出接受的答案,即使这会将可处理的行数限制为32 (由于sql server中的递归函数调用限制).这让我觉得它是系统寿命的可怕解决方案,更不用说为了避免使用简单的光标而付出的巨大努力.

这种疯狂仇恨的原因是什么?有一些"着名的权威"发布了针对游标的法特瓦吗?一些无法形容的邪恶是否潜伏在游戏的核心,腐蚀了儿童的道德或什么?

维基问题,答案比代表更感兴趣.

相关信息:

SQL Server快进游标

编辑:让我更精确:我理解不应该使用游标而不是正常的关系操作 ; 这是一个明智的选择.我不明白的是,即使游标是一种更简单和/或更有效的解决方案,人们也会不顾一切地避开光标,就像他们有傻瓜一样.困扰我的是非理性的仇恨,而不是明显的技术效率.



1> S.Lott..:

游标的"开销"仅仅是API的一部分.游标是RDBMS的部分工作方式.经常CREATE TABLE并且INSERTSELECT语句,而实现是明显的内部游标实现.

使用更高级别的"基于集合的运算符"捆绑将游标结果集合到单个结果集中,这意味着更少的API来回传递.

游标早于提供一流集合的现代语言.旧C,COBOL,Fortran等不得不一次处理一行,因为没有可以广泛使用的"集合"概念.Java,C#,Python等具有包含结果集的一流列表结构.

缓慢的问题

在某些圈子中,关系连接是一个谜,人们会编写嵌套游标而不是简单连接.我已经看到了真正的史诗嵌套循环操作,它被写成了很多很多游标.击败RDBMS优化.而且跑得很慢.

简单的SQL重写以使用连接替换嵌套的游标循环,并且单个平面游标循环可以使程序在第100次运行.[他们以为我是优化之神.我所做的只是用连接替换嵌套循环.仍然使用游标.]

这种混淆常常导致对游标的起诉.但是,它不是光标,而是光标的误用就是问题.

尺寸问题

对于真正的史诗结果集(即将表转储到文件中),游标是必不可少的.基于集合的操作无法将非常大的结果集实现为内存中的单个集合.

备择方案

我尝试尽可能多地使用ORM层.但这有两个目的.首先,游标由ORM组件管理.其次,SQL与应用程序分离为配置文件.并不是游标很糟糕.编码所有打开,关闭和提取的编码不是增值编程.


"游标是RDBMS如何工作的." 如果你的意思是特别是SQL Server,好吧,好吧,我对此一无所知.但我已经研究过多个RDBMS(和ORDBMS)的内部(在Stonebraker下)并且他们都没有这样做.例如:Ingres在内部使用相当于元组"结果集"的内容.
"我已经看到了真正史诗般的嵌套循环操作,它被写成了很多很多游标." 我也一直在看他们.很难相信.

2> Galwegian..:

游标使人们过度地将程序思维模式应用于基于集合的环境.

他们很!

来自SQLTeam:

请注意,游标是访问SQL Server内部数据的最慢方式.只应在真正需要一次访问一行时使用.我能想到的唯一原因是在每一行调用存储过程.在Cursor Performance文章中,我发现游标比基于set的替代方案慢30多倍.


那篇文章已经7岁了,你认为或许事情可能会在此期间发生变化吗?
@BoltBait:我个人认为,如果你做出这样的毯子断言你就不能真正成为45岁:-P
@BoltBait:你的小孩从我的草坪上下来!

3> davidcl..:

上面有一个答案说"游标是访问SQL Server内部数据的最慢方式...游标比基于集合的替代方案慢30多倍."

在许多情况下,这种说法可能是正确的,但作为一揽子声明,这是有问题的.例如,在我想要执行更新或删除操作的情况下,我已经很好地利用了游标,这些操作会影响接收常量生产读取的大型表的许多行.运行一次执行这些更新的存储过程最终比基于集合的操作更快,因为基于集合的操作与读取操作冲突并最终导致可怕的锁定问题(并且可能完全终止生产系统,在极端的情况下).

在没有其他数据库活动的情况下,基于集合的操作普遍更快.在生产系统中,它取决于.


@ [Joel Coehoorn]:我从来没有理解这句话.
@ [Steven A. Lowe]基本上它说的是,如果你用一个子句"破坏规则",就必须有一个通用的规则来打破,因为规则存在.例如From Link :("如果我们有一个声明,例如'星期日免费入场',我们可以合理地假设,作为一般规则,入场费用.")
@ [Steven A. Lowe] http://www.phrases.org.uk/含义/exception-that-proves-the-rule.html将异常理解为“遗漏的内容”,请注意此处的规则类似于“在大多数情况下,游标是错误的”。

4> davidcl..:

游标倾向于在基于集合的操作更好的地方开始使用SQL开发人员.特别是当人们在学习传统编程语言后学习SQL时,"迭代这些记录"的心态往往会导致人们不恰当地使用游标.

最严重的SQL书籍包括一章禁止使用游标; 精心编写的文章清楚地表明游标有它们的位置,但不应该用于基于集合的操作.

很明显,游标是正确的选择,或者至少是正确的选择.



5> Cade Roux..:

当使用游标方法时,优化器通常不能使用关系代数来转换问题.通常游标是解决问题的好方法,但SQL是一种声明性语言,数据库中有很多信息,从约束到统计和索引,这意味着优化器有很多选项可以解决问题,而游标几乎明确指示解决方案.



6> tuinstoel..:

在Oracle PL/SQL游标中,不会导致表锁,并且可以使用批量收集/批量提取.

在Oracle 10中经常使用的隐式游标

  for x in (select ....) loop
    --do something 
  end loop;

一次隐式提取100行.显式批量收集/批量获取也是可能的.

但是PL/SQL游标是最后的手段,当您无法解决基于集合的SQL的问题时,请使用它们.

另一个原因是并行化,数据库比逐行命令式代码更容易并行化基于大型集的语句.这也是函数式编程变得越来越流行的原因(Haskell,F#,Lisp,C#LINQ,MapReduce ......),函数式编程使并行化变得更容易.每台计算机的CPU数量正在增加,因此并行化变得越来越成问题.



7> Charles Bret..:

通常,因为在关系数据库中,使用游标的代码性能比基于集合的操作差一个数量级.


我记得第一次使用SQL时,我们必须将一个50k的每日数据文件从大型机导入到SQL Server数据库中...我使用了一个游标,发现导入大约花了26个小时使用光标.当我改为基于集合的操作时,该过程耗时20分钟.

8> Richard T..:

上面的答案并未充分强调锁定的重要性.我不是游标的忠实粉丝,因为它们经常导致表级锁定.

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有