0

需要帮助很大的时间....

我需要创建一个 .net 应用程序,它将对表中的大约 2,000,000 条记录执行一些批量操作。有一个机会窗口,应用程序应该在其中运行并尝试处理尽可能多的行。我在想,如果我可以让应用程序的多个线程一次获取 2000 条记录并处理它们,它应该能够处理更多。但是,这在数据库服务器上将非常昂贵。据我所知,数据库服务器是一台功能强大的机器,应该能够承受压力。

此外,通过一次只取 2000 行,如果应用程序在其处理过程中终止,它会知道从哪里重新开始。

所以,我想我要问的是......

1)我怎样才能让应用程序拾取行并锁定这些行,以便它不会被分配给另一个线程?

2) 什么样的智能可以编程到应用程序中,使其能够从上次中断的地方继续处理?

谢谢

KP

4

3 回答 3

1

我同意 John 的观点,即 SSIS 为此类场景提供了大量内置智能,并且可能是您投入时间的最佳选择。

作为记录,您可以通过对数据进行分区来解决此类问题。我不是在谈论物理存储分区(即添加表分区),而是逻辑处理分区。你分割你的200万。N 个分区中的记录,基于您可以在数据访问级别利用的任何标准,例如。一个索引列,然后分配 N 个处理器,每个处理器在自己的分区上开始搅动。这个想法是不要让处理器在尝试访问相同的行时重叠。“处理器”可以是线程,或者更好的是 ThreadPool 将使用异步数据库访问方法的工作项排队。

最大的问题是很多时候您没有合适的分区键。在这种情况下,您可以像这样进行临时分区:

with cte as (
   select top (@batchSize) *
   from myTable with (rowlock, updlock, readpast)
   where <record is ready to be processed>)
update cte
   set <mark record processing>
output inserted.*

诀窍是选择中使用的锁定提示:通过强制和上锁,记录被锁定以供当前处理器处理。通过添加 readpast 提示,每个处理器将跳过已被其他处理器锁定的记录。这样,无论处理是什么,每个处理器都会获得自己的 @batchSize 批记录来处理。

重要的是要理解所有这些注释都适用于涉及数据库之外的某些内容的处理,例如进行 Web 服务调用、打印纸条或任何类似的东西。如果处理全部在数据库中,那么您应该将其表达为单个 T-SQL 更新,并让查询优化器使用它认为合适的并行查询。

于 2009-07-31T19:21:49.443 回答
1

与其重新发明轮子,不如使用 SQL Server Integration Services (SSIS) 来完成。它针对这些场景进行了高度优化,尤其是在 2008 版本中。

于 2009-07-31T19:07:15.340 回答
0

我会这样做:

  • 设置一个表(最初是空的)来保存主行的 PK。称之为 PKs_Done_Table
  • 一个线程“从 pk 不在的表中选择 blah(从 PKs_done_Table 中选择 pk)
  • 同一个线程从此选择中抓取行(或行块 - 使用 NTILE 或多次读取)并将它们交给其他线程进行实际处理。

处理线程:

  • 接受行/行块
  • 开始交易
  • 做这项工作
  • 将完成工作的 pks 插入 PKs_done_table
  • 提交事务。

这应该可以让你有很大的吞吐量和安全的重启,前提是你可以在任何时候让你的一些表不被处理。如果不是这种情况,那么无论如何重新启动都是没有意义的。

于 2013-08-09T01:16:20.397 回答