插入大量行的最快方法是什么?


27

我有一个数据库,在其中我将文件加载到临时表中,从该临时表中我有1-2个连接来解析一些外键,然后将这些行插入到最终表中(每月有一个分区)。我有大约34亿行用于三个月的数据。

使这些行暂存到最终表中的最快方法是什么?SSIS数据流任务(使用视图作为源并激活快速加载)或插入INTO SELECT ....命令?我尝试了“数据流任务”,并在5个小时内可以得到大约10亿行(8核/服务器上192 GB RAM),这对我来说感觉很慢。


1
分区是否位于单独的文件组上(并且位于不同物理磁盘上的那些文件组上)?
亚伦·伯特兰

3
一个非常好的资源,《数据加载性能指南》。这解决了您可以执行的许多性能优化,例如,启用TF610,使用BCP OUT / IN,SSIS等。您只需遵循建议并在您的环境中对其进行测试。
Kin Shah

@Aaron是的,每月有一个文件组,附加了12个San lun,因此所有jan都放在一个lun上,等等。不确定每个lun有多少磁盘,但应该足够。
nojetlag

是的,我的意思是“磁盘集”,也许还可以提到控制器,它们可能变得饱和。
亚伦·伯特兰

@Kin看了一下该指南,但似乎已经过时了,“ SQL Server目标是将数据从Integration Services数据流批量加载到SQL Server的最快方法。此目标支持SQL Server的所有批量加载选项– ROWS_PER_BATCH除外。” 在SSIS 2012中,他们建议使用OLE DB目标以获得更好的性能。
nojetlag

Answers:


25

一种常用方法:

  1. 在目标表上禁用/删除索引/约束。
  2. INSERT dbo.[Target] WITH (TABLOCKX) SELECT ...
  3. 归功于JNK,您可以分批执行上述操作n,这可以减轻事务日志的压力,当然,这意味着如果某个批处理失败,则只需从该批处理开始即可。我在此发布了有关此内容的博客(引用删除时,也应用了相同的基本概念):http : //www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
  4. 在目标表上重新启用/重新创建索引/约束(也许您可以推迟其中的一些操作,如果它们不是所有操作所必需的,并且使基本数据快速联机更重要)。

如果您的分区是物理分区,而不仅仅是逻辑分区,那么可以通过让不同的进程同时填充不同的分区来获得一些时间(当然这意味着您不能使用TABLOCK/ TABLOCKX)。这假定源也适合于多个进程的选择,而无需选择重叠/锁定等,并使操作的这一端更加缓慢(提示:在源上创建适合于目标分区方案的聚簇索引)。

您还可以考虑一些更原始的东西,例如BCP OUT/BCP IN

我不知道我会跳到SSIS来解决这个问题。那里可能有一些效率,但我不知道这种努力可以证明节省了费用。


2
如果您的数据未排序,请勿盲目删除索引(尤其是聚集索引)。删除索引并期望重新创建聚簇索引可能是一个巨大的错误,因为它可能会花费大量磁盘空间和大量时间。我不是第一个遇到这种错误的人。查看本文sqlmag.com/t-sql/…中的“计划B”描述。作者有同样的问题。
jyao 2016年

10

从SSIS的角度看您的问题,我觉得这样做可能花了很长时间的原因是您没有进行批处理。这可能会导致SSIS管道中填充过多行,从而可能会阻碍SSIS性能。您需要做的是更改每批设置的行数,并可能更改最大插入提交大小。现在,您也对此进行了设置将取决于SSIS服务器可用的内存量?您的SQL Server实例的磁盘速度是多少?最好的方法是测试。例如使用10,000。这将一次向服务器10,000发送一批,从而防止您的管道溢出,并有助于更快地运行此过程。这些设置在您的OLEDB目标中设置。

OLEDB目的地

如果存在问题,您还可以按照@AaronBertrand的建议在操作前后添加执行SQL任务,并删除/重新向表添加任何索引或约束。


1
关于DBA.SE的其他地方需要什么“快速加载”,这是一个很好的问题:dba.stackexchange.com/questions/141430/…
所有行业的乔恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.