You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQL Server中:VALUES与SELECT/UNION ALL多行INSERT哪个更快?

SQL Server两种多行INSERT语句的性能对比解析

嘿,你的测试结果确实有点反直觉对吧?本来以为其中一种会更快,结果实际跑出来的情况和预期不一样——咱们来好好拆解下为什么会这样。

1. 两种写法的底层执行逻辑差异

首先得明确:在SQL Server里,INSERT...VALUES(...)(多行语法)和INSERT...SELECT...UNION ALL的执行计划并不是一成不变的,优化器会根据你的场景调整处理方式。

  • 对于INSERT...VALUES:这是SQL Server 2008开始引入的原生批量插入语法,优化器会把它识别为“Table Valued Constructor”操作。但当你每次只插入10行这种小批量数据时,这个构造操作的额外开销(比如解析多行值的结构)可能会被放大。
  • 对于INSERT...SELECT...UNION ALL:UNION ALL是非常轻量的结果集拼接方式,因为它不需要去重、排序,优化器可以直接把多个SELECT的结果合并成一个数据集插入。在小批量多次执行的场景下,这种拼接的成本反而比Table Valued Constructor更低。

2. 你的测试场景放大了差异

你是每10行执行一次INSERT,总共要跑1800多次插入操作——这才是关键!

默认情况下,每一次单独的INSERT都是一个独立事务,事务的提交、日志写入的开销其实非常大,这部分开销会成为整个测试的主要性能瓶颈。而两种写法在事务内的细微性能差异,经过1800多次的累计,就变成了你看到的25分钟 vs 27分钟的差距。

3. 更准确的测试建议

如果想真正对比两种写法的性能,不妨调整测试方式:

  • 一次性插入所有18704行:不要拆分多次,这时候优化器可以针对大批次数据做更高效的批量处理,两种写法的性能会更接近,甚至可能INSERT...VALUES会反超。
  • 把所有插入放在一个事务里:比如用以下代码包裹所有INSERT语句,这样能大幅减少事务提交的重复开销,让两种写法的真实性能差异显现出来:
    BEGIN TRANSACTION;
    -- 所有INSERT语句放在这里
    COMMIT TRANSACTION;
    
  • 查看执行计划:针对单次插入10行的情况,打开SQL Server的执行计划查看功能,看看两种写法有没有额外的运算符(比如不必要的排序、数据转换)导致性能差异。

最后要说明的是:性能测试结果非常依赖具体场景——批量大小、SQL Server版本、硬件配置、日志模式(简单/完整)都会影响最终结果,你的测试结果是符合当前场景的,并不是绝对的“谁比谁快”。

内容的提问来源于stack exchange,提问作者victorf

火山引擎 最新活动