【问题标题】:Fastest way to read/write to sql server with a large dataset?使用大型数据集读取/写入 sql server 的最快方法?
【发布时间】:2011-04-04 09:14:24
【问题描述】:

我在数据库中有大约 6000 万条记录,并且必须处理所有这些记录。所以想法是使用 c# 代码读取数据,处理它,然后将其放回数据库中。数据不会在同一个表中来来去去 - 涉及多个表。

我想看看最好的方法是什么?我是否应该在数据集中一次读取 10 万条记录,然后处理每条记录,然后使用批量插入数据库,然后读取下一组?

【问题讨论】:

  • 试图做什么类型的“处理”?一般来说,这种类型的操作最好使用更接近数据的东西来完成,比如 DTS/SSIS,但这取决于你对数据的实际操作。
  • +1 达米安的评论。就像他提到的那样,需要更多关于您对数据所做的事情的信息!!

标签: c# sql performance dataset


【解决方案1】:

不要靠近 DataSet 或 DataAdapter!

要获取数据,请使用 DataReader - 通过调用 ExecuteReader 来通过 SqlCommand 使用 SQL 文本或存储过程调用。然后,您可以一次从 DataReader 中检索记录,而无需使用 DateSet、实体框架或 Linq to SQL 或 NHibenate 附带的任何对象跟踪包——所有这些框架都添加了层以允许您执行对象和更改跟踪 - 您不需要并且只会为您带来开销。

当您将结果写回数据库时,请通过 SqlBulkCopy 执行此操作,启用 TableLock 并将数据库属性设置为“恢复模型”而不是“完整”。确保目标表上的约束被禁用,并且没有定义任何索引(然后删除并在最后重新创建,如果需要)。

SqlBulkCopy 在发送回 SQL Server 时会进行自己的批处理,前提是您确保指定了 BatchSize(默认为一批中的所有内容)。您可能还想在 SqlBulkCopy 上设置 UseInternalTransaction,以便每个批次都在自己的事务中完成 - 这将进一步减少事务日志的使用。

读者和作者线程可能会有所帮助,也可能不会,我没有充分说明差异。如果您提到的“第三方进程”很耗时,您可能还需要一个或多个处理线程或其他一些机制。

可以在一个线程上完成所有这些操作,一次一条记录,而且速度非常快(取决于您正在执行的处理成本)。

如果您确实需要使用多个线程,则不要在此期间交换单个记录,因为您将丢失太多 CPU 周期线程切换:将其分块为“合理”的批次。 “合理”可能在 1k 到 100k 条记录之间,具体取决于记录大小和您所做的处理。甚至可以让 Parallels 为您做这件事。

鉴于您说涉及多个表,可能只为每个源表启动一个线程可能会很好地工作,并锁定写入 SqlBlukCopy 对象以进行同步。

【讨论】:

  • 或者您使用 BlToolking/Linq2Data,它允许对象阅读器在使用 LINQ 时无需进行所有跟踪;;)
【解决方案2】:

通常,绝对最快的方法是以 SQL 批处理的形式在服务器上执行所有操作。

如果您坚持使用客户端,那么单独的线程来读取和写入会比使用一个来执行这两个线程更快。读写多少线程取决于硬件和你在做什么

编辑:澄清方法。

检索数据并将数据发送到 sql server 是网络 IO 绑定和进程外的。这意味着在读取和发送数据时,您的应用程序都会花费时间等待数据通过网络从磁盘传输到内存中。让我们假设检索数据需要 1 小时。处理 10 分钟,将数据发送回数据库需要 1 小时。所以整个过程需要 2 小时 10 分钟。

如果将其拆分为三个线程,1 个读取器,1 个处理器,1 个更新器。您可以将其缩短到接近 1 小时。如果你的应用程序写得很好,你可以添加额外的线程来读取、处理和写入,但你可能会对结果感到失望,因为共享缓存线、网卡如何响应大量并发请求等。

此外,当您使用 DataAdapter 填充数据集时,在填充完成之前您不能接触任何数据。另一方面,如果您是 DataReader,则可以在第一行完成时开始使用数据。这意味着您不必担心一次限制为 100K。

【讨论】:

  • +1 用于单独的线程(尽管我认为每个线程都进行读/处理/写都很好)。另外,不要使用 LINQ to SQL。它确实受到巨大数据集内存泄漏的影响。
  • 不,我无法在 sql server 中完成所有操作。我必须打电话给第三方来处理数据。那么,读取数据集中的 100K 行并处理并将数据放回并在 10 个线程中完成所有这些操作是最快的方法吗?
猜你喜欢
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多