【问题标题】:partial results from a long-running SELECT query?长时间运行的 SELECT 查询的部分结果?
【发布时间】:2011-01-10 22:17:09
【问题描述】:

我们正在对 mysql 数据库发出一些长时间运行的查询。 (上下文是离线数据分析,而不是应用程序。)我们将如何进行研究取决于我们在此过程中获得的结果。如果能够在查询完成之前查看(部分)结果由 SELECT 语句生成,这对我们很有用。

这可能吗?还是我们一直等到查询完成(考虑到数据集的大小可能需要几个小时)才能查看在它运行的最初几秒钟内生成的结果?

感谢您的帮助。

【问题讨论】:

  • 为什么不使用 LIMIT 拆分结果?
  • @Moak:谢谢你的想法!但是我们尝试了这个,不幸的是它不起作用。将“LIMIT 0, one_fifth_of_the_returned_records”附加到查询的运行时间与没有 LIMIT 的相同查询一样长。它不会在较短的时间内产生前五分之一的结果。
  • 如果您实际上可以以完整形式发布长期运行的查询之一,那么在这里避免“心理答案”当然会容易得多。
  • 欢迎来到 2018,一切都没有改变,但我可以告诉你的是,你可以尝试在查询中引入索引,这样WHERE + LIMIT 会更快

标签: sql mysql database select


【解决方案1】:

我会冒险猜测您的查询中有 ORDER BYGROUP BY

我使用过的大多数数据库引擎都会尽快将数据流式传输回客户端,即使它还没有在内部全部获取它们。但是,一旦您将GROUP BYORDER BY 放入混合中,引擎在生成整个服务器端数据集之前不知道第一行会是什么样子,这就是您等待的原因很久了。

【讨论】:

  • GROUP BY 可能没问题,如果没有聚合函数(如果 GROUP BY 在功能上只是一个 DISTINCT)
【解决方案2】:

最简单的尝试是使用无缓冲查询。然后 mysql 将尽快开始交付数据,而不是在一切准备就绪(并缓冲)时。根据您的查询,这可能无济于事。

要真正加快速度,您需要分解查询。不只是使用 LIMIT,根据您的查询,这不会为您节省很多时间。例如,如果您有一个 ORDER BY,则几乎必须首先计算整个结果集。您只会节省通过网络传输更少数据所需的时间。

通过过滤器拆分您的查询。如果您有一个已编入索引的字段,您可以对其进行范围搜索(即自动递增),然后使用该字段将您的查询分解为多个查询。例如:

SELECT * FROM db WHERE field1 BETWEEN 1 AND 10000;
SELECT * FROM db WHERE field1 BETWEEN 10000 AND 20000;
...

然后您可以在之后组合结果。很多时候,像这样的多个查询将比等效的单个查询更快地完成。但是,如果您确实有 ORDER BY 或 GROUP BY,这可能是不可能的。 但是您仍然可以尝试将其分解为较小的查询,使用 UNION 将它们连接起来,然后使用您的分组和排序方式在 UNION 上进行选择。信不信由你,这仍然比等效的单个查询要快得多。您只需让单个查询处理足够小的数据集以使其快速。

SELECT field1, SUM(field3) field3, SUM(item_count) item_count FROM 
(
SELECT field1, SUM(field3) field3, COUNT(item) item_count FROM db WHERE field1 BETWEEN 1 AND 10000 GROUP BY field1
UNION
SELECT field1, SUM(field3) field3, COUNT(item) item_count FROM db WHERE field1 BETWEEN 10000 AND 20000 GROUP BY field1
UNION
...
) AS sub_queries GROUP BY field1

分而治之。使用这种技术,我有时可以将查询时间从一小时缩短到一两分钟。

【讨论】:

    【解决方案3】:

    很抱歉将此添加为新答案,但“添加评论”按钮仍未显示:

    @Lasse,

    对我来说,这个问题听起来像是 OP 对“中间了解正在计算的运行总和的当前值”感兴趣。

    那是不可能的,句号。

    如果 OP 的问题与您所指出的方向相反,即获取“完整结果集的早期子集”,那么我的建议当然是诉诸配额查询技术。你知道,“优化 20 行”之类的东西。

    【讨论】:

    • 我同意,如果最终结果取决于首先实现的一切,那么根本无法知道这一点。这就像试图给你迄今为止在人口普查中统计的人数的百分比,但在你真正统计完所有人之前不知道存在多少人。
    • 声望达到 50 时,您可以添加 cmets,但也许您已经知道这一点。在任何情况下都欢迎使用 Stack Overflow :)
    • 我在代表得分为 11 时添加了此评论 :-)
    【解决方案4】:

    在“完整”查询仍在进行时返回中间结果,这违背了 SQL 甚至关系模型最初的构思。

    RM 甚至 SQL 都被设计为只返回完整和最终的结果,一旦它们被“完全和最终”计算出来。

    如果您想获得基于人口子集的最终结果在统计上可靠的近似值,则必须求助于统计和外推技术。

    【讨论】:

    • 然而,对于大多数数据库引擎来说,尽快开始将结果流式传输回客户端是完全正常的。一些结果集可能会占用服务器的很大一部分内存,如果它真的很大,甚至可能占用磁盘,如果服务器没有真正的理由首先在服务器端生成整个数据集,它通常会开始传输尽快行批处理,以避免必须全部缓存。但是,排序和分组需要一个完整的生产服务器端才能开始流式传输。
    猜你喜欢
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 2013-03-08
    相关资源
    最近更新 更多