我正在建立一个通过各种CSV Feed更新大量数据的系统。通常我会循环遍历Feed中的每一行,执行select查询以检查项目是否已存在,并根据项目是否存在插入/更新项目。
我觉得这种方法的可扩展性不高,可能会使服务器受到更大的反馈。我的解决方案是正常循环项目,但将它们存储在内存中。然后,对于每100个左右的项目,对这100个项目进行选择,并获得数据库中匹配的现有项目列表。然后将insert / update语句连接在一起并将它们运行到数据库中。这基本上可以减少到数据库的行程。
这是一个可扩展的解决方案吗?是否有关于将大型Feed导入高效环境的示例教程?
由于
答案 0 :(得分:14)
看到您正在使用SQL Server 2008,我建议采用这种方法:
查看有关如何使用MERGE命令的MSDN docs和great blog post。
基本上,您在实际数据表和登台表之间根据通用条件(例如公共主键)创建链接,然后您可以定义在
时执行的操作你会得到一个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中一个非常强大且非常有用的新命令 - 如果可以,请使用它!
答案 1 :(得分:3)
你的方式是最糟糕的解决方案。一般而言,您不应该考虑单独循环记录。我们曾经有一个公司建立的导入工具循环记录,加载一个超过一百万条记录的文件需要18-20个小时(这在建立时并不常见,但是很多次现在发生的一天)。
我看到两个选择: 首先使用批量插入加载到临时表,并执行需要在该表上执行的任何清理操作。你是如何确定记录是否已经存在的?您应该能够通过连接到确定更新的那些字段上的登台表来构建基于集的更新。通常我在我的临时表中添加了一列,用于匹配的记录的id,并通过查询填充,然后完成更新。然后,您插入没有相应ID的记录。如果您有太多记录可以同时执行所有操作,您可能希望批量运行(这是一个循环),但是使批次一次大于1条记录(我通常从2000开始,然后基于确定我是否可以在批次中做更多或更少的时间。
我认为2008年也有合并声明,但我还没有机会使用它。在网上查阅。
另一种方法是使用针对速度进行优化的SSIS。 SSIS虽然复杂,但学习曲线陡峭。
答案 2 :(得分:2)
一种方法是将CSV加载到DataTable(或更可能是DataReader)中,然后使用SqlBulkCopy批处理结果 -
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx
它非常高效,你可以做一些列映射。提示 - 使用SqlBulkCopy映射列时,它们区分大小写。
答案 3 :(得分:0)
另一种方法是在服务器上的服务器上编写.Net存储过程以对整个文件进行操作...
只有当你需要比Kris Krause的解决方案更多的控制时 - 我很擅长保持简单(和可重复使用)的地方......
答案 4 :(得分:0)
你需要在这里自己动手吗?是否有可能以这样的方式提供数据:SQL Server可以使用批量导入加载它,然后在导入完成后处理数据库中的重复项?
当谈到带有大量数据的繁重工作时,我的经验往往是尽可能多地在数据库中工作更快,更少资源。