【问题标题】:Very slow SQL ORDER BY, and EXPLAIN doesn't explainSQL ORDER BY 很慢,EXPLAIN 没有解释
【发布时间】:2016-02-14 16:46:11
【问题描述】:

查询:

SELECT
    m.*,
    mic.*
FROM
    members m,
    members_in_class_activities mic
WHERE
    m.id = mic.member_id AND
    mic.not_cancelled = '1' AND
    mic.class_activity_id = '32' AND
    mic.date = '2016-02-14' AND
    mic.time = '11:00:00'
ORDER BY
    mic.reservation_order

members 有大约 10 万条记录,而表 members_in_class_activities 有大约 30 万条记录。结果集只有 2 条记录。 (不是 2k,只有 2 个。)

所有相关列均已编入索引(idreservation_order 为主):member_id, not_cancelled, class_activity_id, date, time

还有class_activity_id + member_id + date + time + not_cancelled 的唯一键。 not_cancelledNULL'1'

所有其他查询都非常快(1-5 毫秒),但这个非常慢:600-1000 毫秒。

什么没有帮助:

  • 只选择 2 个主键而不是 *(0 % 变化)
  • 一个真正的JOIN,而不是一个隐式连接(它实际上似乎稍微慢了一点,但可能不是)(0 % 变化)
  • 完全移除与members 的连接使其稍微更快(15 % 变化)

什么有很大帮助:

  • 删除主键上的 ORDER BY(99% 变化)

我只有两个问题:

  1. 什么????
  2. 我如何仍然ORDER BY x,但也让它变得更快?我真的需要单独的专栏吗?

我在我的开发机器上运行 10.1.9-MariaDB,但在生产的 MySQL 5.5.27-log 上也很慢。

【问题讨论】:

  • SHOW CREATE TABLE。一个猜测 - 你正在混合 VARCHARs 和数字。

标签: mysql sql-order-by mariadb


【解决方案1】:

不要在主查询中使用 order by。试试这个:

SELECT * FROM (   
  ... your query
) ORDER BY mic.reservation_order

正如您提到的 members_in_class_activities has about 300k 记录,因此您的 order by 将适用于所有 300k 记录,这肯定会减慢您的查询速度。

【讨论】:

  • 先命令,后条件?这很奇怪......许多其他查询在更大的表上运行,它们的顺序很好。我的 DBAL 做的子查询不太好,所以我得稍后再试。如果真的是这样的话,我对 MySQL 感到非常失望。
  • 在其他 2 个查询上(在这个和另一个更大的表上),它使它慢得多。他们在最大的桌子上也有一个订单。
  • 所以你是说你的查询仍然需要600-1000 ms?
  • 不,这样的速度很快,但我在其他 2 个慢速查询上尝试了它,并在大表上进行了排序,它们像这样慢。既然 EXPLAIN 无法解释,也许你可以。相同类型的交易,但更大的数据集(约 5 M 记录)。结果只有 20 行,但“你的方式”让它变慢了。
  • 您能发表您的疑问吗?我不是 sql 专家,但会研究一下。
【解决方案2】:

class_activity_id + member_id + date + time + not_cancelled -- 不是最优的。

WHERE 中的“=”字段以任意顺序开始,然后添加ORDER BY 字段:

INDEX(class_activity_id, date, time, not_cancelled,
      reservation_order)

由于您似乎需要 UNIQUE 约束,那么通过将 member_id 放在末尾(它将“不碍事”,但未使用)来洗牌您的索引几乎一样好:

UNIQUE(class_activity_id, date, time, not_cancelled, member_id)

一般来说,将datetime 分开是不好的;为该对建议一个 DATETIME 列。

Cookbook on creating indexes.

【讨论】:

  • 索引不是问题。顺序是。查询需要 2ms 没有顺序。组合索引是个好主意。链接进入待办事项列表。
  • 是的,我正在混合 int 和 string。那不好吗?大多数表都有整数和字符串......或者你的意思是在索引内?
  • JOIN ... ON int_column = varchar_columnvarchar_column = 1234
  • 哦。不,但我总是用引号做int_column = '1234'。唯一的列到列比较是m.id = mic.member_id,它们是相同的(根据innodb的要求)。
  • 好吧,也许这不是问题的原因。
猜你喜欢
  • 2023-02-01
  • 2010-10-16
  • 2011-02-22
  • 2016-10-23
  • 2011-09-11
  • 2017-07-13
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
相关资源
最近更新 更多