在 SQL Server 2008 中插入/更新大量数据的最佳实践
-
23-09-2019 - |
题
我正在构建一个系统,用于通过各种 CSV 源更新大量数据。通常我会循环遍历提要中的每一行,执行选择查询来检查该项目是否已存在,并根据项目是否存在插入/更新该项目。
我觉得这种方法的可扩展性不太好,并且可能会在更大的提要上对服务器造成影响。我的解决方案是像平常一样循环遍历这些项目,但将它们存储在内存中。然后,对于每 100 个左右的项目,对这 100 个项目进行选择,并获取数据库中匹配的现有项目的列表。然后将插入/更新语句连接在一起并将它们运行到数据库中。这基本上会减少数据库访问次数。
这是一个足够可扩展的解决方案吗?是否有关于将大型提要导入生产环境的示例教程?
谢谢
解决方案
鉴于您使用的是 SQL Server 2008,我推荐这种方法:
- 首先将 CSV 文件批量复制到暂存表中
- 使用 MERGE 命令从该临时表更新目标表
查看 MSDN 文档 和一个 很棒的博文 关于如何使用 MERGE 命令。
基本上,您可以根据通用标准(例如,在实际数据表和临时表之间创建链接)。一个公共主键),然后您可以定义何时执行操作
- 行匹配,例如该行同时存在于源表和目标表中 --> 通常您会更新某些字段,或者直接忽略它们
- 源中的行不存在于目标中 --> 通常是 INSERT 的情况
你会有一个 MERGE
声明如下:
MERGE TargetTable AS t
USING SourceTable AS src
ON t.PrimaryKey = src.PrimaryKey
WHEN NOT MATCHED THEN
INSERT (list OF fields)
VALUES (list OF values)
WHEN MATCHED THEN
UPDATE
SET (list OF SET statements)
;
当然, ON
如果需要的话,子句可以涉及更多。当然,你的 WHEN
语句也可以更复杂,例如
WHEN MATCHED AND (some other condition) THEN ......
等等。
MERGE
是 SQL Server 2008 中一个非常强大且非常有用的新命令 - 如果可以的话,请使用它!
其他提示
您的方法是最坏的可能的解决方案。在一般情况下,你不应该认为通过循环记录单独的条款。我们曾经有一个公司建成导入工具,通过记录回路,则需18-20小时装载有超过一百万条记录文件(这在过去是不经常发生当它被建立,但它是一个多次天发生现在)。
我看到两个选项: 首先使用批量插入到负载的临时表,做任何清理就需要在该表上做的。你是如何确定的记录已经存在?您应该能够通过加入到临时表上那些确定更新领域建立一个基于集合的更新。我经常有添加一列到我的临时表中为它匹配的记录的ID,人口,通过查询,于是做了更新。然后,你做的不具有相应的ID记录插入。如果你有太多的记录做一次,你可能要分批运行(这是一个循环),但在同一时间做出比1点的记录相当大的批次(我一般用2000开始,然后根据它需要在该时间决定是否能在批量做更多或更少)。
我认为2008年也有合并声明,但我尚未有机会使用它。在书中看到它在线。
在替代方案是使用SSIS其被优化速度。 SSIS是一个复杂的事情虽然和学习曲线是陡。
的一种方法是加载到CSV数据表(或更可能一个DataReader),然后在使用使用SqlBulkCopy结果批次SLAM -
http://msdn.microsoft.com /en-us/library/system.data.sqlclient.sqlbulkcopy.aspx
它非常有效,你可以做一些列映射。提示 - 当您使用映射列的SqlBulkCopy它们是大小写敏感的
。另一种方法是写在服务器一个.net存储过程在服务器上对整个文件进行操作...
只有当你需要比克里斯克劳斯的解决方案更多的控制权,但 - 我保持简单(和可重复使用)的大风扇,我们可以...
你需要在这里所有的滚动你自己?是否有可能提供这样的方式使SQL Server可以使用批量导入来加载它,然后在数据库处理重复一次导入完成后的数据?
当涉及到繁重了很多数据我的经验往往是在数据库中工作,尽可能为更快和资源较少。