Sql 为什么基于关系集的查询比游标更好?
在用TSQL或PLSQL之类的语言编写数据库查询时,我们通常可以选择使用游标对行进行迭代以完成任务,或者编写一条SQL语句同时执行相同的任务 此外,我们还可以选择简单地将大量数据拉回到应用程序中,然后使用C#或Java或PHP或其他工具逐行处理Sql 为什么基于关系集的查询比游标更好?,sql,language-agnostic,cursor,Sql,Language Agnostic,Cursor,在用TSQL或PLSQL之类的语言编写数据库查询时,我们通常可以选择使用游标对行进行迭代以完成任务,或者编写一条SQL语句同时执行相同的任务 此外,我们还可以选择简单地将大量数据拉回到应用程序中,然后使用C#或Java或PHP或其他工具逐行处理 为什么使用基于集合的查询更好?这一选择背后的理论是什么?什么是基于光标的解决方案及其对应关系的好例子?我知道的主要原因是,引擎可以通过跨多个线程运行基于集合的操作来优化它们。例如,设想一个快速排序-您可以将正在排序的列表分成多个“块”,并在各自的线程中分
为什么使用基于集合的查询更好?这一选择背后的理论是什么?什么是基于光标的解决方案及其对应关系的好例子?我知道的主要原因是,引擎可以通过跨多个线程运行基于集合的操作来优化它们。例如,设想一个快速排序-您可以将正在排序的列表分成多个“块”,并在各自的线程中分别对每个块进行排序。SQL引擎可以在一个基于集合的查询中对大量数据执行类似的操作
当您执行基于光标的操作时,引擎只能按顺序运行,并且操作必须是单线程的。首选在查询中执行工作的想法是,数据库引擎可以通过重新格式化来进行优化。这也是为什么您希望在查询中运行EXPLAIN,以查看数据库实际上在做什么。(例如,利用索引、表格大小,有时甚至利用关于列中值分布的知识。) 这就是说,要在实际的具体案例中取得良好的表现,您可能必须遵守或违反规则
哦,另一个原因可能是约束:如果在所有更新之后都检查了约束,则将唯一列的值增加一个可能没问题,但如果逐个执行,则会产生冲突。基于集合的操作只需一次操作即可完成 游标与基于游标集的查询的行集一样多的操作(通常)更快,因为:
--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
我认为真正的答案是,就像编程中的所有方法一样,这取决于哪种方法更好。一般来说,基于集合的语言将更加高效,因为这就是它设计的目的。光标有两个优势位置:
- 它(主观上)更易于阅读。在以后查看代码时,您是希望尝试用循环和其他东西解析复杂的存储过程(或客户端代码),还是希望查看简洁的SQL语句
- 它避免了网络往返。为什么要将所有数据推送到客户端,然后再推回更多数据?如果不需要,为什么要重击网络
- 这是浪费。您的DBMS和应用程序服务器需要缓冲部分/全部数据才能使用。如果您没有无限内存,您可能会调出其他数据;为什么要将可能重要的内容从内存中调出,以缓冲一个几乎无用的结果集
- 你为什么不呢?你