为什么“Select * into targettable from sourcetable”比“insert into targettable select * from sourcetable”快

10 sql-server

这个标题是个问题。我很想知道答案。有人告诉

选择进入最低限度地登录简单恢复模型数据库......我根本没有进入它。

摘自微软:

SELECT...INTO 的日志记录量取决于对数据库有效的恢复模型。在简单恢复模型或大容量日志恢复模型下,批量操作的日志记录最少。通过最少的日志记录,使用 SELECT... INTO 语句比创建表然后使用 INSERT 语句填充表更有效

寻求帮助

谢谢

JNK*_*JNK 11

一些想法/理论:

SELECT INTO...让 RDBMS 根据原始表的顺序确定排序顺序。如果您插入到现有表中,则可能需要进行排序以匹配聚集或非聚集索引。

无索引- 当您SELECT INTO...的 RDBMS 确定没有要更新的预先存在的索引时。

无争用- 由于您要插入的表不存在,SQL Server 无需担心行级锁定或争用处理。没有其他东西可以引用您创建的表,因为它不存在。

尽管如此,还有其他方法可以非常快速地插入表格。

  • 尽可能确保您的聚集索引键匹配。这意味着没有即时排序

  • 禁用所有非聚集索引。不言自明。

  • 将恢复模式设置为简单并将跟踪标志 610 设置为ON. 使用TABLOCK目标表上的提示和NOLOCK源表上的提示。

例如,假设 tablea 和 tableb 具有相同的聚集索引:

INSERT INTO TableB WITH (TABLOCK)
SELECT <Columns>
FROM TableA WITH (NOLOCK)
Run Code Online (Sandbox Code Playgroud)

根据我的经验,这比使用SELECT INTO...然后创建聚集索引要快。请注意,这也适用于已经有数据的表,这是一个更有用的场景。

编辑:

这是来自 MS 的一份非常详细的白皮书,用于 Sql Server 2008 中的数据加载性能。

  • 非常彻底的回答 JNK。此外,当正确实施且恢复模型未满时,简单的 SSIS 数据流任务可能比其中任何一个都快。为什么?以上两者都会发出排他锁(读是多线程,写是单线程)。只要目标适配器使用表锁,SSIS 就会使用批量更新锁(读和写都是多线程的)。 (4认同)