很慢 SQL ORDER BY, EXPLAIN 不解释
Very slow SQL ORDER BY, and EXPLAIN doesn't explain
查询:
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
Table members
有大约 10 万条记录,而 table members_in_class_activities
有大约 30 万条记录。结果集只有 2 条记录。 (不是 2k,只是 2。)
所有相关列都已编入索引(id
和 reservation_order
是主要列):member_id, not_cancelled, class_activity_id, date, time
.
还有 class_activity_id + member_id + date + time + not_cancelled
的唯一键。 not_cancelled
是 NULL
或 '1'
。
所有其他查询都非常快(1-5 毫秒),但这个非常慢:600-1000 毫秒。
什么没有帮助:
- select 只有 2 个主键而不是
*
(0 % 变化)
- 真正的
JOIN
而不是隐式连接(它实际上看起来稍微慢一点,但可能不是)(0 % 变化)
- 完全删除与
members
的连接使其稍微 更快(15% 的变化)
有什么帮助,非常大:
- 删除主键上的 ORDER BY(99% 更改)
我只有两个问题:
- 什么????
- 如何让我仍然
ORDER BY x
,但又让它变快?我真的需要一个单独的专栏吗?
我在我的开发机器上 运行 10.1.9-MariaDB
,但在生产机器上 MySQL 5.5.27-log
也很慢。
不要在您的主查询中使用 order by。试试这个:
SELECT * FROM (
... your query
) ORDER BY mic.reservation_order
正如您提到的 members_in_class_activities has about 300k
条记录,因此您的排序将适用于所有 300k 条记录,这肯定会减慢您的查询速度。
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
放在末尾(它将是 'out of the way' 来调整你的索引几乎一样好但未使用):
UNIQUE(class_activity_id, date, time, not_cancelled, member_id)
一般来说,把date
和time
分开是不好的;为该对建议一个 DATETIME
列。
查询:
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
Table members
有大约 10 万条记录,而 table members_in_class_activities
有大约 30 万条记录。结果集只有 2 条记录。 (不是 2k,只是 2。)
所有相关列都已编入索引(id
和 reservation_order
是主要列):member_id, not_cancelled, class_activity_id, date, time
.
还有 class_activity_id + member_id + date + time + not_cancelled
的唯一键。 not_cancelled
是 NULL
或 '1'
。
所有其他查询都非常快(1-5 毫秒),但这个非常慢:600-1000 毫秒。
什么没有帮助:
- select 只有 2 个主键而不是
*
(0 % 变化) - 真正的
JOIN
而不是隐式连接(它实际上看起来稍微慢一点,但可能不是)(0 % 变化) - 完全删除与
members
的连接使其稍微 更快(15% 的变化)
有什么帮助,非常大:
- 删除主键上的 ORDER BY(99% 更改)
我只有两个问题:
- 什么????
- 如何让我仍然
ORDER BY x
,但又让它变快?我真的需要一个单独的专栏吗?
我在我的开发机器上 运行 10.1.9-MariaDB
,但在生产机器上 MySQL 5.5.27-log
也很慢。
不要在您的主查询中使用 order by。试试这个:
SELECT * FROM (
... your query
) ORDER BY mic.reservation_order
正如您提到的 members_in_class_activities has about 300k
条记录,因此您的排序将适用于所有 300k 条记录,这肯定会减慢您的查询速度。
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
放在末尾(它将是 'out of the way' 来调整你的索引几乎一样好但未使用):
UNIQUE(class_activity_id, date, time, not_cancelled, member_id)
一般来说,把date
和time
分开是不好的;为该对建议一个 DATETIME
列。