【问题标题】:How to improve LIMIT clause in MySQL subquery?如何改进 MySQL 子查询中的 LIMIT 子句?
【发布时间】:2015-06-21 16:05:45
【问题描述】:

我有两个表:posts 有 10k 行和comments,我需要为特定数量的posts 选择所有comments,换句话说,通过posts 表实现分页并获取所有@987654329 @ 其中。为此,我有下一个查询:

select * from  comments c 
inner join (select post_id from posts o order by post_id  limit 0, 10) p 
on c.post_id = p.post_id;

查询的性能对我来说也很重要。但是这个查询的Explain 很奇怪,因为LIMIT 子句遍历9976 rows,但没有像我预期的那样遍历10 行:

同时,当我单独运行子查询时,它可以很好地按预期遍历 10 行:

explain select post_id from posts o order by post_id  limit 0, 10

posts(post_id), comments(comment_id), comments(post_id) 上还有 indexes我不明白该查询有什么问题,因此它遍历了帖子表中的所有记录。如果有人帮助我解决这个问题,我将非常感激。

【问题讨论】:

  • 我相信子选择对于外部选择中的每条记录都会重复迭代,这就是为什么它看起来如此之高。您可能可以重组查询以避免选择子
  • @Vinbot 实际上我不知道如何使用不同的查询结构通过钉合获得相同的结果。能给我举个例子吗?
  • @Siyual 这里没有重复,因为其他分支上的起源问题是关于简单的限制查询,并且有正确的答案。所有其他沟通都是关于更复杂的查询,因此最好将问题分开到不同的分支。
  • @Speise 从好的方面来说,它使用索引,所以它不必去数据库文件来获取值,它从索引中提取值非常快。用 1,000,000 条记录加载您的帖子表,看看它有多快。

标签: mysql sql performance subquery limit


【解决方案1】:

首先,您的 qwuery 没有迭代超过 9976 行。 Explain 显示查询将读取的行数的估计值(实际上,它会生成许多执行计划并丢弃除成本估计值最低的之外的所有执行计划)。

对于限制 0,10,它可能会读取更少的行(取决于索引的配置方式),但当被要求解决限制 10000、10 时,它会读取更多

【讨论】:

  • 但是还有一个问题——为什么 MySQL 估计子查询与同一个单独的查询不同?
  • 因为子查询需要返回一个有序集来高效查找他的其他表
【解决方案2】:

9976(与 10000 相比)已经是一种改进——在 5.6 之前,“行”通常相差 2 倍。现在统计数据更准确、更稳定。

真正的答案是“EXPLAIN 并不完美。”

5.7 将有一些的改进。与此同时,我们还被“10 vs 9976”之类的谜团所困。

当使用 LIMIT 时,它大多被破坏。它以另一种方式体现在EXPLAIN EXTENDED 的“已过滤”列中。

试试EXPLAIN FORMAT=JSON ... 以获取更多信息。

使用 MariaDB(版本 10.0?),ANALYZE SELECT ... 将为您提供实际计数。它通过运行查询,然后抛出结果集并保留统计信息来做到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多