Ash*_*ish 3 performance sql-server database-internals
如果我有一个包含许多索引的表,并且我运行了一个将行插入到表中的语句,SQL Server 是一次插入一个行,还是使用并行性插入行?
Pau*_*ite 11
我运行了一条将行插入表中的语句,SQL Server 是一次插入一个行,还是使用并行性?
在 SQL Server 2016 之前,单个T-SQL INSERT语句始终使用一个执行计划,该执行计划使用单个逻辑处理器插入行并维护关联的非聚集索引。这回答了您问题的一方面。
“一次一个”插入行的问题需要一些解释。从根本上说,INSERT...SELECT执行计划中的数据修改始终作为一个或多个按串行顺序执行的一次或多个行流运行。
也就是说,查询优化器通常可以在两种执行计划策略之间进行选择:
第一个选项意味着每一行都被插入到基表中,所有非聚集索引都按串行顺序更新,然后再移动到下一行。这被称为窄或每行插入策略。
第二个选项意味着在对每个非聚集索引做同样的事情之前,所有的行都被插入到基表(尽管一次仍然是一个),再次以串行序列。这称为宽插入或按索引插入策略。
优化器为每个非聚集索引在窄和宽策略之间做出基于成本的选择,因此很常见的情况是,执行计划在与基表相同的运算符中维护一些非聚集索引,而其他索引则使用单独的运算符维护.
宽/每索引策略还允许潜在的优化,例如按每个索引的键顺序对行集进行排序,以促进顺序访问模式。
您可以在我的博客文章优化更改数据的 T-SQL 查询中找到有关此内容和执行计划示例的更多详细信息。
有一个反馈建议允许并行维护非聚集索引。它在 Connect 上受到好评(后来迁移到新平台),但该想法尚未实现。
虽然它仅限于用于数据修改的单个处理器,但INSERT...SELECT可以在标识和创建要插入的数据的计划部分中使用并行性。从 SQL Server 2016 开始,INSERT...SELECT可以对堆执行并行插入。
为获得最佳插入性能,请检查您的查询是否满足最少记录操作的标准,可能需要跟踪标志 610。详细信息可在数据加载性能指南 中找到。
您可能还想使用其他允许使用多个进程进行并行插入(有一些警告)的 SQL Server 工具进行调查:
T_SQL BULK INSERT (来自文件)bcp实用程序SELECT INTO 确实允许并行(Server 2014+),但这要求在进程开始之前该表不存在,并且之后必须添加任何非聚集索引。
如果您使用的是企业版,分区表为优化批量插入提供了额外的可能性。同样,请参阅数据加载性能指南了解详细信息。
我写的相关文章: