从远程服务器检索数十亿行?
Posted
技术标签:
【中文标题】从远程服务器检索数十亿行?【英文标题】:Retrieving billions of rows from remote server? 【发布时间】:2011-10-15 12:38:39 【问题描述】:我正在尝试从远程 SQL Server 检索大约 2000 亿行。为了优化这一点,我将查询限制为仅使用索引列作为过滤器,并且仅选择列的子集以使查询看起来像这样:
SELECT ColA, ColB, ColC FROM <Database> WHERE RecordDate BETWEEN '' AND ''
但看起来除非我将查询限制在几个小时的时间窗口内,否则查询在所有情况下都会失败并出现以下错误:
OLE DB provider "SQLNCLI10" for linked server "<>" returned message "Query timeout expired".
Msg 7399, Level 16, State 1, Server M<, Line 1
The OLE DB provider "SQLNCLI10" for linked server "<>" reported an error. Execution terminated by the provider because a resource limit was reached.
Msg 7421, Level 16, State 2, Server <>, Line 1
Cannot fetch the rowset from OLE DB provider "SQLNCLI10" for linked server "<>".
超时可能是一个问题,因为执行查询计划需要时间。由于我无法控制服务器,我想知道除了我正在使用的简单 SELECT
之外,是否有一种很好的方法来检索这些数据。我可以使用任何特定于 SQL Server 的技巧吗?也许告诉远程服务器对数据进行分页而不是发出多个查询或其他什么?关于如何改进这一点的任何建议?
【问题讨论】:
【参考方案1】:这更像是SSIS 适合的工作。即使是像 ReadFromOleDbSource->WriteToOleDbSource 这样的简单流程也可以处理这个问题,为您创建必要的批处理。
【讨论】:
+1,我相信这是一个更合适的答案,因为要完成超过 2000 亿行的ROW_NUMBER
将是一件非常困难的事情【参考方案2】:
为什么要一次读取 2000 亿行?
你应该分页,一次读几千行。
即使您确实需要读取所有 2000 亿行,您仍然应该考虑使用分页将读取分解为更短的查询 - 这样,如果发生故障,您只需从中断的地方继续阅读。
请参阅efficient way to implement paging 了解至少一种使用ROW_NUMBER
实现分页的方法
如果您正在进行数据分析,那么我怀疑您使用了错误的存储(SQL Server 并不是真正为处理大型数据集而设计的),或者您需要更改查询以便在使用 SQL 的服务器。
更新:我认为最后一段被误解了。
SQL Server 中的存储主要是为online transaction processing (OLTP) 设计的 - 在大规模并发环境中高效查询海量数据集(例如读取/更新数十亿数据库中的单个客户记录,同时成千上万的其他用户正在对其他记录做同样的事情)。通常,目标是尽量减少读取的数据量,减少所需的 IO 量并减少争用。
您所说的分析几乎与此完全相反——单个客户端积极尝试读取几乎所有记录以执行一些统计分析。
是的,SQL Server 会处理这个问题,但您必须记住,它针对完全不同的场景进行了优化。例如,数据一次从磁盘读取一页 (8 KB),尽管您的统计处理可能仅基于 2 或 3 列。根据行密度和列宽,您可能只使用了存储在 8 KB 页面上的一小部分数据——SQL Server 必须读取和分配内存的大部分数据甚至没有被使用。 (请记住,SQL Server 还必须锁定该页面,以防止其他用户在读取数据时弄乱数据)。
如果您认真对待海量数据集的处理/分析,那么有一些存储格式专门针对这类事情进行了优化 - SQL Server 还有一个名为 Microsoft Analysis Services 的附加服务,它增加了额外的 online analytical processing (OLAP) 和数据挖掘能力,使用更适合这种处理的存储模式。
【讨论】:
SQL Server 什么时候不是为大型数据集设计的?我已经在 SQL Server 中管理了数十亿行,并且没有遇到在其他 RDBMS 系统中不会遇到的任何挑战。 @Aaron -- SQLServer,尤其是企业版附带的附加组件,是进行此类分析的绝佳平台。 @James 我认为我们意见一致。 Kragen 建议 SQL Server 不是为这么多数据而设计的。一定是在考虑古代版本。 @Kragen,SQL Server 可以很好地处理数十亿行,而且它已经能够这样做很长时间了。回到 SQL 2000(当时是 2003 年),我在一个表中管理数十亿行。 SQL Server 6.5 可能会遇到这么多数据负载的问题,但那是很久以前的事了。 @Kragen -- 我认为我们真的同意 -- 它的分析服务插件真的让它摇滚!【参考方案3】:如果我想一次提取这么多数据,我个人会使用 BCP 等数据提取工具将数据获取到本地文件,然后再尝试操作它。
http://msdn.microsoft.com/en-us/library/ms162802.aspx
【讨论】:
【参考方案4】:这不是 SQL Server 特定的答案,但即使 rDBMS 支持服务器端游标,使用它们也被认为是糟糕的形式。这样做意味着您正在消耗服务器上的资源,即使服务器仍在等待您请求更多数据。
相反,您应该重新规划您的查询用法,以便服务器可以尽快传输整个结果集,然后完全忘记您和您的查询,为下一个查询让路。当结果集太大而无法一次性处理时,您应该跟踪当前批次返回的最后一行,以便您可以从该位置开始获取另一个批次。
【讨论】:
因为他只有 ODBC 访问服务器,所以很难看出他如何使用除了“SELECT”之外的任何东西。 服务器端游标,在支持它们的 rDBMS 中,是连接的属性,完全独立于用于生成结果集的 SQL 语句。【参考方案5】:很可能远程服务器设置了“远程查询超时”。查询失败需要多长时间?
【讨论】:
从 SSMS 到大约 10 分钟。使用 sqlcmd 大约需要 3 个小时。 10 分钟超时真的让我觉得这是远程超时设置,因为 10 分钟是默认设置。如果这是问题所在,则需要在远程端更改此设置。不知道为什么 sqlcmd 会运行 3 个小时然后死掉。在运行、计划生成、等待其他事情等之前可能正在做其他事情。【参考方案6】:刚刚遇到同样的问题,运行查询后我也在 10:01 收到了消息。
检查此link。 Connections 下有一个远程查询超时设置,默认设置为 600 秒,您需要将其更改为零(无限制)或您认为正确的其他值。
【讨论】:
【参考方案7】:尝试更改远程服务器连接超时属性。
为此转到 SSMS,连接到服务器,在对象资源管理器中右键单击服务器名称,进一步选择 Properties -> Connections
并更改 Remote query timeout (in seconds, 0 = no timeout)
文本框中的值。
【讨论】:
以上是关于从远程服务器检索数十亿行?的主要内容,如果未能解决你的问题,请参考以下文章
通过 PostgreSQL 数据库聚合大型(数十亿行)数据集
OAuth2.0部署不当,数十亿Android App账户存泄露风险