MySQL不使用LIMIT来优化查询选择功能吗?

时间:2017-04-17 20:53:32

标签: mysql database optimization query-optimization

我有一个复杂的查询,我必须在一个给我一些性能问题的应用程序中运行。我在这里简化了它。该数据库是CentOS上的MySQL 5.6.35。

SELECT a.`po_num`, 
       Count(*)          AS item_count, 
       Sum(b.`quantity`) AS total_quantity, 
       Group_concat(`web_sku` SEPARATOR ' ') AS web_skus 
FROM   `order` a 
       INNER JOIN `order_item` b 
               ON a.`order_id` = b.`order_key` 
WHERE  `store` LIKE '%foobar%'
LIMIT  200 offset 0; 

此查询的关键部分是我已放置" foobar"作为占位符。如果此值类似于big_store,则查询需要更长时间(在此处提供的查询中大约0.4秒,在我实际使用的查询中要长得多),而不是值为small_store(在查询中大约为0.1秒) )。如果没有限制,big_store会返回更多的结果。

但是有一个限制,这让我感到惊讶。两个数据集都超过LIMIT,只有200.在我看来,MySQL为所有big_store / small_store行执行选择函数COUNTSUMGROUP_CONCAT然后追溯应用LIMIT。我想,当你到达200时,它最好停下来。

在抓取它将使用的200行之后,它是否可以执行选择功能COUNTSUMGROUP_CONCAT操作,使我的查询更加快速?这对我来说似乎是可行的,除非在其中一行上有ORDER BY

MySQL是否不使用LIMIT来优化查询选择功能?如果没有,那有充分的理由吗?如果是这样,我上面的想法是否犯了错误?

1 个答案:

答案 0 :(得分:1)

由于LIMIT,它可以停止播放,但这不是一个合理的查询,因为没有ORDER BY

如果没有ORDER BY,它会选择它感觉到的200行并停止。

使用ORDER BY时,必须扫描包含store的整个表格(限定列来自哪个列!)。这是因为前导通配符。只有这样才能修剪到200行。

另一个问题 - 没有GROUP BY,聚合(SUM等)会在整个表格中执行(或者至少在过滤后保留的那些表格)。 LIMIT 之前 不适用

也许您所询问的是MariaDB 5.5.21的“LIMIT_ROWS_EXAMINED”。

以这种方式思考...... SELECT的所有组件都是按语法指定的顺序完成的。由于LIMIT是最后一个,因此在执行其他内容之后才会适用。

(有几个例外:(1)SELECT col...必须在FROM ...之后完成,因为它不知道哪个表;(2)优化器很容易重新排序{{1 JOINed中的表和子句。)

有关该查询的更多详情。

  1. 优化器向前看,看到WHERE ... AND ...正在WHERE上过滤(order是哪里,是吗?),所以它决定从表{{}开始1}}。
  2. store获取与order匹配的所有行。
  3. 对于每个这样的行,找到order中的行。现在它有一些行(可能超过200)用于聚合。
  4. 执行汇总 - %foobar%order_itemCOUNT。 (实际上这可能会在收集行时进行 - 另一种优化。)
  5. 现在有一行(a。SUM的值不可预测。)
  6. 跳过GROUP_CONCAT po_num部分的0行。 (好吧,另一个无序的东西。)
  7. 最多可提供200行。 (只有1个。)
  8. 添加OFFSET(但没有LIMIT) - 大不了,排序1行。

    添加ORDER BY(但没有GROUP BY),现在您可能有超过200行,并且可以停止。

    添加GROUP BY ORDER BY 它们是相同的,然后可能必须进行排序分组,但不是为了排序,它可能在200停止。

    添加GROUP BY ORDER BY 他们相同,然后可能必须对分组进行排序,并且必须重新排序以进行排序,并且在之后 GROUP BY之前不能停在200。也就是说,几乎所有的工作都是在所有数据上进行的。

    哦,如果你没有最佳指数,所有这一切都会变得更糟。哦,我没有坚持提供ORDER BY吗?

    我为我的语气道歉。我向你的方向投了很多小窍门;请向他们学习。