如何编写高性能SQL存储过程循环_巧用集合代替游标操作

游标在SQL Server中性能极差,因其逐行处理、频繁触发查询计划和锁申请,应优先用CTE+ROW_NUMBER()分批处理或临时表+WHILE替代;仅极少数场景(如动态邮件发送)才需谨慎使用FAST_FORWARD只读游标。为什么游标在SQL Server里慢得像爬虫因为游标是逐行取、逐行处理,每次 fetch 都触发一次查询计划执行和锁资源申请,CPU 和 I/O 压力直接翻倍。尤其当 SELECT 返回上万行时,DECLARE CURSOR + FETCH NEXT 组合几乎必然成为性能瓶颈。真正该问的不是"怎么优化游标",而是"能不能根本不用游标"。答案通常是:能,而且必须换。游标默认是 KEYSET 或 STATIC 类型,内存开销大,且不支持并行执行WHILE 循环配合 TOP 1 + ORDER BY 模拟游标?更糟------它反复扫描表,没有索引友好性哪怕加了 WITH (NOLOCK),也只缓解读阻塞,不解决逻辑层低效用CTE + ROW_NUMBER()批量切片替代单行游标核心思路:把"一行一行处理"变成"一批一批处理",用集合运算一次生成所有需要的数据上下文,再通过窗口函数打序号,最后用 WHERE rn BETWEEN @start AND @end 分页驱动业务逻辑。适用于需按顺序处理但无强事务依赖的场景,比如日志归档、状态批量更新、中间表填充。先用 ROW_NUMBER() OVER (ORDER BY id) 给目标数据编号,别用 NEWID() ------ 它让排序不可控,且无法复用索引分片大小建议设为 5000~10000 行,太小则循环次数多;太大则单次事务日志暴涨,易触发 LOG FULL务必在 ORDER BY 字段建索引,否则 ROW_NUMBER() 会强制 SORT,内存消耗陡增WITH numbered AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY created_time) AS rn FROM orders WHERE status = 'pending')UPDATE o SET status = 'processed'FROM orders oINNER JOIN numbered n ON o.id = n.idWHERE n.rn BETWEEN @offset + 1 AND @offset + @batch_size;临时表 + WHILE 循环的可控批量方案当业务逻辑复杂到无法全写进一个 UPDATE 或 INSERT ... SELECT 时,用临时表暂存主键集,再用 WHILE 控制批次,比游标轻量得多,且每批可独立提交事务。 arXiv Xplorer ArXiv 语义搜索引擎,帮您快速轻松的查找,保存和下载arXiv文章。

相关推荐
如夏倾城2 小时前
百度文心(容易被忽略的好用AI)使用方式
人工智能·python·百度·语言模型·dubbo
用户019027581612 小时前
quotes 实时价和 klines 最新收盘价为什么对不上?
python
星恒随风3 小时前
MySQL 从零入门(六):复合查询详解——多表查询、自连接、子查询与 UNION
linux·服务器·数据库·mysql
少司府3 小时前
嵌入式入门篇(二):初识STM32F103ZET6
linux·python·stm32·单片机·嵌入式硬件·mcu·嵌入式软件
打工仔折腾 AI4 小时前
Changedetection.io 网页变动监控:Docker 部署、通知配置与公网暴露实践
运维·人工智能·后端·python·docker·容器·性能优化
火云代理4 小时前
Python 使用代理 IP 前,先弄清 Requests 的配置来源与验证方法
网络·python·网络协议·tcp/ip·ip
无奈笑天下4 小时前
银河麒麟上lsblk命令教程详解
linux·运维·服务器·数据库
金銀銅鐵5 小时前
一个 4 个常量的枚举,Kotlin 在字节码里生成了什么
jvm·kotlin
xiaoye-duck6 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
2601_967979126 小时前
Python第七十四讲 异常处理完全精通 try-except零基础保姆级教程
python·异常处理·编程教程·错误处理·try-except