MySQL 查询 Order By Clause 花费太多时间
MySQL Query Order By Cluase taking too much time
我有一个查询只用了 .001 秒,没有按部分排序。但是当我在查询中添加 order by 时,它需要大约 0.736 秒的时间。时间太多了。我已经将该列编入索引,但它没有按预期工作。
这里是查询:
SELECT DISTINCT
n0_.id AS id0, n0_.published_at AS published_at1
FROM
news n0_
INNER JOIN
news_translations n1_ ON n0_.id = n1_.translatable_id
WHERE
((n0_.unpublished_at IS NOT NULL
AND (CURRENT_TIMESTAMP >= n0_.published_at
AND CURRENT_TIMESTAMP < n0_.unpublished_at))
OR (CURRENT_TIMESTAMP >= n0_.published_at
AND n0_.unpublished_at IS NULL))
AND
(n0_.status = 1
AND n0_.content_type_id = 1)
AND n1_.locale = 'zh_CN'
and n0_.id NOT IN (139476 , 226, 225, 224, 223, 218, 213, 69, 65, 62)
GROUP BY n0_.id
#ORDER BY n0_.published_at DESC
LIMIT 10 OFFSET 0;
这是 SHOW KEYS 的输出:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type
news 0 PRIMARY 1 id A 139656 NULL NULL BTREE
news 0 UNIQ_1DD399501204232D 1 comment_box_id A 139656 NULL NULL YES BTREE
news 1 IDX_1DD39950510C33D5 1 approval_type_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD399501A445520 1 content_type_id A 36 NULL NULL YES BTREE
news 1 IDX_1DD39950A76ED395 1 user_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD3995042A9A1DE 1 smiley_group_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD39950B3FE509D 1 survey_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD3995029C1004E 1 video_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD399501CDF82CA 1 cover_image A 4 NULL NULL YES BTREE
news 1 IDX_1DD399504E7AF8F 1 gallery_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD399506048130B 1 home_position_id A 4 NULL NULL YES BTREE
news 1 news_published_at_index 1 published_at A 139656 NULL NULL BTREE
排序是一项开销很大的操作,因此对很多行进行排序需要时间。一种方法是在订购前削减结果,但这并不总是可行的。
还要考虑在您的 table 中可以找到哪些其他模式并加以利用。我很确定,您的数据总是按 id 升序排列(也可能是发布时间)。如我所见,您按发布时间排序,因此如果数据自然按 table 中的此列排序,您可以利用它来发挥自己的优势。
但要确保是这样,所以没有例外。例如,如果您在插入新行时总是使用 NOW(),那么它们很有可能是有序的。
我有一个查询只用了 .001 秒,没有按部分排序。但是当我在查询中添加 order by 时,它需要大约 0.736 秒的时间。时间太多了。我已经将该列编入索引,但它没有按预期工作。
这里是查询:
SELECT DISTINCT
n0_.id AS id0, n0_.published_at AS published_at1
FROM
news n0_
INNER JOIN
news_translations n1_ ON n0_.id = n1_.translatable_id
WHERE
((n0_.unpublished_at IS NOT NULL
AND (CURRENT_TIMESTAMP >= n0_.published_at
AND CURRENT_TIMESTAMP < n0_.unpublished_at))
OR (CURRENT_TIMESTAMP >= n0_.published_at
AND n0_.unpublished_at IS NULL))
AND
(n0_.status = 1
AND n0_.content_type_id = 1)
AND n1_.locale = 'zh_CN'
and n0_.id NOT IN (139476 , 226, 225, 224, 223, 218, 213, 69, 65, 62)
GROUP BY n0_.id
#ORDER BY n0_.published_at DESC
LIMIT 10 OFFSET 0;
这是 SHOW KEYS 的输出:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type
news 0 PRIMARY 1 id A 139656 NULL NULL BTREE
news 0 UNIQ_1DD399501204232D 1 comment_box_id A 139656 NULL NULL YES BTREE
news 1 IDX_1DD39950510C33D5 1 approval_type_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD399501A445520 1 content_type_id A 36 NULL NULL YES BTREE
news 1 IDX_1DD39950A76ED395 1 user_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD3995042A9A1DE 1 smiley_group_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD39950B3FE509D 1 survey_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD3995029C1004E 1 video_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD399501CDF82CA 1 cover_image A 4 NULL NULL YES BTREE
news 1 IDX_1DD399504E7AF8F 1 gallery_id A 4 NULL NULL YES BTREE
news 1 IDX_1DD399506048130B 1 home_position_id A 4 NULL NULL YES BTREE
news 1 news_published_at_index 1 published_at A 139656 NULL NULL BTREE
排序是一项开销很大的操作,因此对很多行进行排序需要时间。一种方法是在订购前削减结果,但这并不总是可行的。
还要考虑在您的 table 中可以找到哪些其他模式并加以利用。我很确定,您的数据总是按 id 升序排列(也可能是发布时间)。如我所见,您按发布时间排序,因此如果数据自然按 table 中的此列排序,您可以利用它来发挥自己的优势。 但要确保是这样,所以没有例外。例如,如果您在插入新行时总是使用 NOW(),那么它们很有可能是有序的。