SQL Server 2014两类UPDATE语句性能对比及执行分析方法咨询
两个UPDATE语句的性能对比与验证方案
首先直接给结论:语句2的执行速度会明显更快,尤其是在你的场景下(WHERE条件能过滤90%的行)。下面详细拆解原因、验证方法和索引优化建议:
为什么语句2更快?
咱们得先搞懂SQL Server处理UPDATE的逻辑:
- 语句1没有WHERE条件,会遍历表中每一行,哪怕
flname里根本没有'('字符。更关键的是,哪怕replace后的结果和原字段值完全一样,SQL Server仍然会标记这一行为“已更新”,生成事务日志、修改页结构,白白消耗IO和CPU资源。 - 语句2通过
where flname<>replace(flname,'(','')过滤出真正需要修改的行(也就是包含'('的10%数据),只对这些行执行更新操作。这意味着事务日志量减少90%,IO操作大幅降低,CPU也不用浪费在无意义的计算上。
怎么用工具验证性能差异?
SQL Server自带了很多工具可以直观对比两者的性能:
- 执行计划(Execution Plan):
打开SSMS,选中两个语句,点击“显示估计的执行计划”(Ctrl+L),或者直接执行时选“包括实际执行计划”(Ctrl+M)。你会看到语句1的操作是Table Scan(或Clustered Index Scan)加上Update,而语句2的扫描范围会小很多,还会多一个Filter操作来筛选需要更新的行。重点看“逻辑读取”“物理读取”这些指标,语句2的数值会远低于语句1。 - 统计IO和时间:
执行前先运行这两个命令:
然后分别执行两个UPDATE语句,查看输出的“消息”面板:SET STATISTICS IO ON; SET STATISTICS TIME ON;- 语句1会显示大量的逻辑读(对应全表扫描的页数量),执行时间更长;
- 语句2的逻辑读和CPU时间都会大幅降低,因为只处理10%的行。
- SQL Server Profiler/Extended Events:
如果需要更细粒度的跟踪(比如锁等待、日志生成量),可以用Profiler(适合简单场景)或者Extended Events(更轻量,推荐),跟踪SQL:BatchCompleted事件,对比两者的Duration、Reads、Writes指标。
关于索引的优化建议
你提到flname字段目前无索引,创建索引确实能进一步提升语句2的性能:
- 直接创建非聚集索引在
flname上:
虽然CREATE NONCLUSTERED INDEX IX_tablename_flname ON tablename(flname);WHERE条件里用到了replace函数,没法用索引seek,但SQL Server可以通过扫描这个非聚集索引来筛选符合条件的行——非聚集索引的页数量远小于全表,扫描速度比全表扫描快很多,能更快定位到需要更新的10%数据。 - 进阶:如果频繁需要这类字符串替换查询,可以考虑创建计算列索引:
然后把语句2改成:ALTER TABLE tablename ADD flname_no_paren AS REPLACE(flname, '(', ''); CREATE NONCLUSTERED INDEX IX_tablename_flname_no_paren ON tablename(flname_no_paren);
这样SQL Server可以直接用索引seek来找到需要更新的行,性能会更上一层楼。UPDATE tablename SET flname=flname_no_paren WHERE flname <> flname_no_paren;
内容的提问来源于stack exchange,提问作者George Menoutis
相关产品推荐
相关产品推荐

