每天,公司都会将可能有许多记录(350,000)的文本文件放到我们的安全FTP上。我们创建了一个在AM早期运行的Windows服务,将文本文件读入我们的SQL Server 2005数据库表。我们不进行BULK Insert,因为数据是关系型的,我们需要根据数据库中已有的数据进行检查,以确保数据保持标准化和一致。
问题在于服务可能需要很长时间(小时)。这是有问题的,因为它正在插入和更新到我们的应用程序不断需要查询和扫描的表中,这可能会影响数据库和应用程序的性能。
我们想到的一个解决方案是在一个单独的数据库上运行服务,其中包含与我们的实时数据库相同的表。当服务完成后,我们可以在实时数据库中执行BCP,以便它反映服务创建的所有新记录。
我以前从未在数据库中处理过数百万条记录,而且我不确定这样的标准方法是什么。这是做这种事情的合适方式吗?有什么建议吗?
答案 0 :(得分:2)
我看到的一种机制是将值插入临时表 - 使用与目标表相同的模式。空ID表示新记录,填充ID表示更新记录。然后使用SQL Merge命令将其合并到主表中。合并将比单独的插入/更新表现更好。
单独执行此操作,您将需要维护表中的索引 - 如果选择调整则可能会很昂贵。我相信合并它的批量行动。
这里有人提到: What's a good alternative to firing a stored procedure 368 times to update the database?
有关于SQL合并的MSDN文章,因此Google搜索将帮助您。
更新:结果证明你无法合并(你可以在2008年)。您有另一个数据库的想法通常由SQL复制处理。我再次在生产中看到用于执行长时间运行的当前数据库的副本(在此实例中报告和聚合数据),但是这并没有合并。我不知道有哪些合并功能可用在SQL Replication中 - 但它是一个好看的地方。
要么是这样,要么解决无法批量插入/更新的原因。
更新2:,如评论中所述,您可以坚持使用临时表的想法将数据导入数据库,然后在此表中插入/更新联接以填充主表。不同之处在于,SQL正在使用一个集合,因此可以相应地调整任何索引重建 - 即使加入也应该更快。
更新3:您可以从插入过程中删除数据检查并将其移至服务中。如果您在这种情况下可以停止插入表格,那么这将允许您解决阻止批量插入的问题(即,您正在检查基于列值的重复项,因为您还没有奢侈品ID)。或者使用临时表的想法,您可以添加WHERE条件以首先查看数据库中是否存在该行,如:
INSERT INTO MyTable (val1, val2, val3)
SELECT val1, val2, val3 FROM #Tempo
WHERE NOT EXISTS
(
SELECT *
FROM MyTable t
WHERE t.val1 = val1 AND t.val2 = val2 AND t.val3 = val3
)
答案 1 :(得分:2)
我们做的进口比以往任何时候都多。创建一个SSIS pacakge来完成工作。我个人更喜欢创建一个临时表,清理它,然后进行更新或导入。但是如果你想在插入之前,SSIS可以在内存中进行所有清理工作。
答案 2 :(得分:0)
在开始镜像和复制数据之前(这是复杂且昂贵的),检查现有服务以确保其有效运行是值得的。
也许通过添加索引可以摆脱表扫描,或者通过执行智能错误处理可以摆脱查找查询?分析您的服务执行的查询的执行计划并优化这些计划。