我从未尝试过这个,所以我不知道是否会遇到内存问题。
但是 SqlDataReader 是否能够读取万亿条记录?它全部是流式的,对吗?我对 SQL/TDS 协议背后的运作还有些陌生。
更新:请将 Trillion 翻译为非常大的数字。我可能应该说 10 亿或者 1 亿。
我从未尝试过这个,所以我不知道是否会遇到内存问题。
但是 SqlDataReader 是否能够读取万亿条记录?它全部是流式的,对吗?我对 SQL/TDS 协议背后的运作还有些陌生。
更新:请将 Trillion 翻译为非常大的数字。我可能应该说 10 亿或者 1 亿。
有一些细节。
SqlDataReader通常会将整个行读入内存并缓存。这包括任何BLOB字段,因此您可能会在内存中缓存几个2GB的字段(XML、VARBINARY(MAX)、VARCHAR(MAX)、NVARCHAR(MAX))。如果这些字段是一个问题,那么您必须向ExecuteReader传递CommandBehavior.SequentialAccess并使用SqlClient特定类型的流功能,例如SqlBytes.Stream。
连接在SqlDataReader完成之前处于忙碌状态。这会创建事务问题,因为您将无法在同一事务中在数据库中进行任何处理,因为连接正忙。尝试打开不同的连接并在同一事务中注册将失败,因为禁止回路分布式事务。解决方案是使用MARS。您可以通过在连接上设置MultipleActiveResultSets=True
来实现这一点。这允许您在数据读取器仍处于活动状态时在相同的连接上发出命令(典型的获取-处理-获取循环)。仔细阅读Christian Kleinerman的链接,确保您理解MARS和事务周围的问题和限制,它们非常微妙和反直觉。
客户端中的长时间处理将阻塞服务器。您的查询仍将执行所有这些时间,并且当通信管道填满时,服务器将不得不暂停它。查询消耗worker(如果它具有并行计划,则可能需要多个),而工作线程是服务器中非常稀缺的资源(它们大致相当于线程)。 您将无法承受许多客户端以自己的节奏处理巨大的结果集。
事务大小。在一个事务中处理万亿条记录永远不会起作用。日志将必须增长以容纳整个事务,并且不会截断和重用VLF,从而导致巨大的日志增长。
恢复时间。如果在第9990亿条记录处处理失败,它将不得不回滚所有已完成的工作,因此需要另外'12'天才能回滚。
是的,那样可以流式处理...但我不认为你应该尝试这样做。
即使你每秒钟能读取一百万条记录(这听起来对我来说不太可能),你仍需要12天才能读取一万亿条记录......那是很多工作,有风险在中途失去。
现在我意识到你可能并不真的想读取一万亿条记录,但我的观点是,如果你可以将你的"大量"工作分成逻辑批次,那可能是一个好主意。
是的 - 这可能需要一些时间(只要您的SQL不会做任何傻事尝试拍摄快照或其他任何事情),但如果您的服务器可以流式传输,SqlDataReader就不应该有内存使用问题。