【问题标题】:SQL Server and SqlDataReader - Trillion Records - MemorySQL Server 和 SqlDataReader - 万亿记录 - 内存
【发布时间】:2010-12-23 09:04:02
【问题描述】:

我从未尝试过这个 - 所以我不知道我是否会遇到内存问题。

但是 SqlDataReader 可以读取一万亿条记录吗?这一切都流式传输正确吗?我对 SQL/TDS 协议在幕后所做的事情有点不理解。

更新 将万亿翻译为非常大的数字。我可能应该说 10 亿或 1 亿。

【问题讨论】:

  • 您打算阅读一万亿条记录吗?还是只是为了兴趣?

标签: .net sql-server ado.net sqldatareader datareader


【解决方案1】:

有一些细节。

  • SqlDataReader 通常会读取内存中的一整行并将其缓存。这包括任何 BLOB 字段,因此您最终可以在内存中缓存几个 2GB 字段(XML、VARBINARY(MAX)、VARCHAR(MAX)、NVARCHAR(MAX))。如果需要考虑此类字段,则必须将 CommandBehavior.SequentialAccess 传递给 ExecuteReader 并使用 SqlClient 特定类型的流功能,例如 SqlBytes.Stream

  • 在 SqlDataReader 完成之前,连接一直处于忙碌状态。这会产生事务问题,因为您将无法在同一个事务中对数据库中的任何处理,因为连接很忙。尝试打开不同的连接并注册同一事务将失败,因为环回分布式事务被禁止。建议使用MARS。您可以通过在连接上设置MultipleActiveResultSets=True 来实现。这允许您在数据读取器仍处于活动状态(典型的 fetch-process-fetch 循环)时在 same 连接上发出命令。仔细阅读 Christian Kleinerman 的链接,确保您了解 MARS 和交易的问题和限制,它们非常微妙且违反直觉。

  • 客户端中的冗长处理将阻塞服务器。您的查询仍将一直执行,当通信管道填满时,服务器将不得不暂停它。一个查询消耗一个worker(或者更多,如果它有并行计划)并且工作是服务器中一个非常稀缺的商品(它们大致等同于线程)。 您将无法负担许多客户在自己的空闲时间处理大量结果集。

  • 事务大小。在一次交易中处理一万亿条记录永远不会奏效。日志必须增长以适应 整个 事务,并且不会截断和重用 VLF,从而导致 巨大 日志增长。

  • 恢复时间。如果在第 9990 亿条记录处处理失败,则必须回滚所有已完成的工作,因此仅回滚还需要“12”天。

【讨论】:

  • 非常好的信息。 +1 如果数据只需要最终一致,事务在系统中扮演什么角色?您建议一次批处理 1000 或 10000 个的正确方法是什么? (参见 Jon Skeet 的 cmets)
  • 创建可以安全恢复的批次的正确方法取决于正在完成的实际任务。一个简单的例子是有一个具有“当前”聚集键值的表。在事务中,您从表中获取值,按聚集键顺序选择接下来的 10k 行,处理它们,更新表中的当前键值,提交。冲洗、循环并重复。
【解决方案2】:

是的,它会流式传输...但我认为您实际上不应该尝试这样做。

如果您每秒可以读取 100 万条记录(这在我看来不太可能),您仍然需要 12 天才能读取 1 万亿条记录……这需要大量工作,可能会在中途丢失。

现在我意识到您可能并不真的想从字面上阅读一万亿条记录,但我的观点是,如果您无论如何都可以将“大量”工作分成逻辑批次,那就是可能是个好主意。

【讨论】:

  • 所以我最初的问题是什么是 ADO.NET 和 SQL Server 的最佳批处理策略......那么一次处理 1000 条记录的最佳方法是什么。假设您正在执行 MapReduce 类型的活动。我意识到还有其他工具(开放和商业),但如果你工作的公司不允许你使用它们……它们对我没有好处。 (除了试图借用想法)
  • 关于 12 天 +1 的要点。也许我选的数字太高了。
  • 老实说,最好的批处理策略将取决于任务的确切性质。即使查询在以后运行,您能否可靠地将其拆分为批次?能不能提前分批次,给不同的电脑分不同的批次?是否还有其他内容写入此数据?有合适的索引吗?基本上,这是一种以可查询且有效的形式拆分数据的方法。
  • 所以这些问题是我一直在努力解决的问题。当我处于流程中间时,人们可能正在写入数据。我没有一个好的“快照”策略。那是我真正想动脑筋的那个。
  • 起初可能是一台服务器(4 核)处理数据。到年底可能会有两到三台服务器。考虑在这个项目中使用一些 F#。看起来很适合。
【解决方案3】:

是的 - 这可能需要一段时间(只要您的 SQL 没有做任何愚蠢的事情来尝试拍摄快照或其他任何事情),但如果您的服务器可以将其流式传输,则 SqlDataReader 不应该有内存使用问题.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 2013-05-28
    • 1970-01-01
    相关资源
    最近更新 更多