10

我有一组非常大的数据(约 300 万条记录),需要按每日计划与更新和新记录合并。我有一个存储过程,它实际上将记录集分解为 1000 个记录块,并将MERGE命令与临时表一起使用,以避免在数据更新时锁定活动表。问题是它并没有完全帮助。该表仍然“锁定”,并且我们使用数据的网站在尝试访问数据时会收到超时。我什至尝试将它分成 100 个记录块,甚至尝试WAITFOR DELAY '000:00:5'看看它是否有助于在合并块之间暂停。它仍然相当缓慢。

我正在寻找有关如何在不锁定表的情况下合并大量数据的任何建议、最佳实践或示例。

谢谢

4

3 回答 3

7

在执行选择时将前端更改为使用 NOLOCK 或 READ UNCOMMITTED 。

您不能 NOLOCK MERGE、INSERT 或 UPDATE,因为必须锁定记录才能执行更新。但是,您可以 NOLOCK 选择。

请注意,您应该谨慎使用它。如果脏读没问题,那么继续。但是,如果读取需要更新的数据,那么您需要走一条不同的路径并弄清楚为什么合并 3M 记录会导致问题。

我敢打赌,大部分时间都花在了合并命令期间从磁盘读取数据和/或解决内存不足的情况。最好将更多内存塞入数据库服务器。

理想的数量是有足够的内存来根据需要将整个数据库拉入内存。例如,如果您有一个 4GB 的数据库,那么请确保您有 8GB 的​​ RAM ......当然是在 x64 服务器中。

于 2010-07-20T21:07:24.907 回答
5

恐怕我有完全相反的经历。我们正在执行更新和插入,其中源表的行数只有目标表的一小部分,目标表有数百万行。

当我们在整个操作窗口中合并源表记录,然后只执行一次 MERGE 时,我们看到性能提高了 500%。我对此的解释是,您只需为 MERGE 命令的前期分析支付一次费用,而不是在一个紧密的循环中一遍又一遍地进行分析。

此外,我确信将 160 万行(源)合并为 700 万行(目标),而不是将 400 行合并为 700 万行,超过 4000 个不同的操作(在我们的例子中)可以更好地利用 SQL 服务器引擎的功能。同样,相当多的工作是分析两个数据集,而且只完成一次。

我要问的另一个问题是,您是否知道 MERGE 命令在源表和目标表上的索引性能更好?我想向您推荐以下链接:

http://msdn.microsoft.com/en-us/library/cc879317(v=SQL.100).aspx

于 2012-06-28T20:18:44.783 回答
0

从个人经验来看,MERGE 的主要问题是,由于它确实页面锁定,因此它排除了指向表的 INSERT 中的任何并发。因此,如果您沿着这条路走下去,那么您将批处理所有将在单个写入器中命中表的更新是基本的。

例如:我们有一个表,其中 INSERT 每个条目花费了疯狂的 0.2 秒,大部分时间似乎都浪费在事务锁定上,所以我们将其切换为使用 MERGE,一些快速测试表明它允许我们插入 256 个条目在 0.4 秒甚至 0.5 秒内 512 秒内,我们使用负载生成器对此进行了测试,一切似乎都很好,直到它进入生产环境并且页面锁上的所有内容都被阻塞到地狱,导致总吞吐量比单个 INSERT 低得多。

解决方案不仅是在 MERGE 操作中对来自单个生产者的条目进行批处理,而且还通过附加级别的队列(以前每个 DB 的单个连接,但是使用 MARS 来交错所有生产者对执行实际 MERGE 事务的存储过程的调用),这样我们就可以毫无问题地每秒处理数千个 INSERT。

在你所有的前端读取中都有 NOLOCK 提示是绝对必须的,永远都是。

于 2017-03-09T16:47:39.310 回答