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

为什么基于关系集的查询比游标更好?

如何解决《为什么基于关系集的查询比游标更好?》经验,为你挑选了4个好方法。

当在TSQL或PLSQL之类的东西中编写数据库查询时,我们通常可以选择使用游标迭代行来完成任务,或者制作一个同时执行相同作业的单个SQL语句.

此外,我们可以选择简单地将大量数据拉回到我们的应用程序中,然后使用C#或Java或PHP或其他任何方式逐行处理.

为什么使用基于集合的查询更好?这个选择背后的理论是什么?什么是基于游标的解决方案及其关系等效的一个很好的例子?



1> Matt Hamilto..:

我所知道的主要原因是引擎可以通过在多个线程上运行来优化基于集合的操作.例如,考虑一个快速排序 - 您可以将您要排序的列表分成多个"块",并在每个线程中单独排序.SQL引擎可以在一个基于集合的查询中使用大量数据执行类似的操作.

执行基于游标的操作时,引擎只能按顺序运行,操作必须是单线程的.



2> Matt Rogish..:

除了上面的"让DBMS完成工作"(这是一个很好的解决方案)之外,还有其他一些很好的理由将查询留在DBMS中:

它(主观地)更容易阅读.在稍后查看代码时,您是否愿意尝试使用循环和事物解析复杂的存储过程(或客户端代码),或者您更愿意查看简洁的SQL语句?

它避免了网络往返.为什么要将所有数据推送到客户端再推回更多?如果你不需要,为什么要捣乱网络呢?

这很浪费.您的DBMS和应用服务器需要缓冲部分/全部数据才能对其进行处理.如果你没有无限的记忆,你可能会把其他数据分页; 为什么要从内存中挖出可能重要的东西来缓冲一个大多无用的结果集?

你为什么不呢?您购买(或以其他方式使用)高度可靠,速度非常快的DBMS.你为什么不用它?


你忘了提到SQL的查询优化和声明性质; 游标和其他基于行的方法确切地定义了如何检索/处理数据,其中SQL查询仅定义要执行的操作 - 然后RDBMS可以根据统计信息自由地提出最佳计划(例如,取决于统计信息索引)寻求可能更糟或更好的方法然后索引扫描; RDBMS可以区分;基于行的方法不能...)

3> Mark Bracket..:

基于集合的查询(通常)更快,因为:

    他们有更多信息供查询优化器优化

    他们可以从磁盘批量读取

    回滚,事务日志等涉及的日志记录较少.

    减少了锁定,从而减少了开销

    基于集合的逻辑是RDBMS的重点,因此它们已经针对它进行了大量优化(通常以牺牲程序性能为代价)

然而,将数据拉出到中间层以处理它可能很有用,因为它消除了DB服务器的处理开销(这是最难扩展的事情,并且通常也在做其他事情).此外,您通常在中间层中没有相同的开销(或收益).诸如事务日志记录,内置锁定和阻塞等等 - 有时这些是必要且有用的,有时它们只是浪费资源.

一个简单的游标,带有程序逻辑和基于集合的示例(T-SQL),它将根据电话交换分配区号:

--Cursor
DECLARE @phoneNumber char(7)
DECLARE c CURSOR LOCAL FAST_FORWARD FOR
   SELECT PhoneNumber FROM Customer WHERE AreaCode IS NULL
OPEN c
FETCH NEXT FROM c INTO @phoneNumber
WHILE @@FETCH_STATUS = 0 BEGIN
   DECLARE @exchange char(3), @areaCode char(3)
   SELECT @exchange = LEFT(@phoneNumber, 3)

   SELECT @areaCode = AreaCode 
   FROM AreaCode_Exchange 
   WHERE Exchange = @exchange

   IF @areaCode IS NOT NULL BEGIN
       UPDATE Customer SET AreaCode = @areaCode
       WHERE CURRENT OF c
   END
   FETCH NEXT FROM c INTO @phoneNumber
END
CLOSE c
DEALLOCATE c
END

--Set
UPDATE Customer SET
    AreaCode = AreaCode_Exchange.AreaCode
FROM Customer
JOIN AreaCode_Exchange ON
    LEFT(Customer.PhoneNumber, 3) = AreaCode_Exchange.Exchange
WHERE
    Customer.AreaCode IS NULL



4> HLGEM..:

你想要一些现实生活中的例子.我的公司有一个光标,花了40多分钟处理30,000条记录(有时我需要更新超过200,000条记录).没有光标需要45秒才能执行相同的任务.在另一种情况下,我删除了一个光标,并将处理时间从24小时发送到不到一分钟.一个是使用values子句而不是select的插入,另一个是使用变量而不是连接的更新.一个好的经验法则是,如果它是插入,更新或删除,您应该寻找一种基于集合的方式来执行任务.

游标有它们的用途(或者代码首先不是它们的代码),但是在查询关系数据库时它们应该是非常罕见的(除了经过优化以使用它们的Oracle).它们可以更快的一个地方是根据前面记录的值(运行总计)进行计算.甚至应该测试.

使用游标的另一个有限情况是进行一些批处理.如果您尝试以基于集合的方式一次性执行太多操作,则可以将表锁定到其他用户.如果你有一个真正大的集合,最好将它分解为较小的基于集合的插入,更新或删除,这些插入,更新或删除不会过长地保持锁定,然后使用游标运行集合.

游标的第三种用途是通过一组输入值运行系统存储过程.这仅限于一般的小集合,没有人应该搞乱系统过程,这对管理员来说是可以接受的.我建议不要对用户创建的存储过程执行相同的操作,以便处理大批量并重用代码.编写一个基于集合的版本会更好,因为在大多数情况下,性能应该胜过代码重用.

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