包装在事务中后,SQL Server 2008大插件仍然很慢

我一直在查询查询中的一个大INSERT问题:

INSERT table_name
SELECT .....;

该表没有索引,需要大约2000万行才能插入.我在我们的一台服务器上运行SQL Server 2008 R2中的查询.原来的表演大约是40分钟.然后,我在这里阅读帖子告诉我将INSERT包装在BEGIN TRANSACTION / COMMIT中.我做到了,花了大约6分钟.

但是,当我尝试在接下来的几次运行事务包装查询时,时间回到40分钟,就像TRANSACTION效果消失一样.我不知道在接下来的运行中发生了什么.任何的想法?

加:

另一个post表示TRANSACTION旨在用于数据一致性而非性能,建议每5K行批量插入.如何将单个INSERT SELECT语句分解为批处理?我很迷惑.

更新:

实际上,我发现性能改进不是来自TRANSACTION,而是可能来自服务器端表缓存,因为我接下来几次运行,性能就像5分钟.

最佳答案 当您在事务中包装许多INSERT … VALUES语句时,可能会大量加速,因为您不必在每次插入后将脏数据页写入磁盘.但是,当您在显式事务中包装单个INSERT … SELECT时,没有加速,因为甚至之前存在隐式事务,并且机制尚未真正更改.很可能同时在您的环境中发生了其他变化.

逐渐的性能下降可能是由于目标表增长,或者数据库因此而增长.前者永远不会停止增长,随着数据库的不断增长,后者可能变得更加变化/不可预测,所以它可能不是一个下降,这是一种趋势.

如果您始终可以确保将数据插入空表,请考虑更加激进并且每次都丢弃它.使用SELECT INTO而不是INSERT … SELECT.这可能适用于您的参照完整性需求,也可能不适用.不同语法的优点是不同的日志记录策略.

如果在下一次插入之前无法删除该表,但是您可以确保在INSERT操作期间其他连接永远不会访问该表,您可以使用隔离级别或表提示来锁定您的方式;然而,对于类似目标来说,更安全的方法是TABLOCK提示.通过在开始时锁定整个表格,这种提示类似于极端相反;其他所有人都被排除在外,没有时间花在行级锁定上.

插入按目标表的(群集)主键排序的数据.您可以考虑在INSERT期间暂时禁用其他索引,但不要轻易这样做,因为它只是严重损害任何并发流量(如果存在)的另一种方式.

观看你的mdf文件大小.避免您看到它以小增量自动增长的情况.

最后的手段:做一些硬件利用率规划并对目标表进行分区.为此,您需要从“更快,更快”的心态切换到“我需要达到这个速度”的心态.维护起来要复杂得多.

点赞