MySQL 8 慢,综合指数下降
MySQL 8 slow with descending composite index
我有以下查询:
SELECT
shows.id,
shows.title,
shows.thumbnail,
shows.views,
shows.likes,
shows.dislikes,
shows.duration,
shows.hd,
shows.origin,
UNIX_TIMESTAMP(shows.upload_date) as upload_date
FROM
shows
WHERE
(shows.views, shows.id) < (0, 272990)
and shows.visible = 1
ORDER BY
shows.views DESC,
shows.id DESC
LIMIT
32
在 MySQL 8.0.15 中大约需要 0.8 秒。
我试过这样的索引:
CREATE INDEX views_desc_id_desc_visible ON shows (views desc, id desc, visible)
还有这样的:
CREATE INDEX views_desc_id_desc ON shows (views desc, id desc)
以及许多其他排列。我已经删除了它们并从头开始重做了很多次。 Visible 自身确实有一个索引。
当我进行 expain 时,我看到它仅在使用名为 views_desc_id_desc_visible 的键时执行 "Using where"。从查询中删除 visible 不会改变它的性能。删除两个 desc(因此:按视图排序,id)确实使它成为 0.0008 秒。
为什么这不会更快?
更新(从评论中复制)
SELECT shows.id, shows.title, shows.thumbnail, shows.views, shows.likes,
shows.dislikes, shows.duration, shows.hd, shows.origin,
UNIX_TIMESTAMP(shows.upload_date) as upload_date
FROM shows
WHERE (shows.views <= 0)
and not (shows.views = 0 and shows.id >= 272990)
and visible = 1
ORDER BY shows.views DESC, shows.id DESC
LIMIT 32
修复它。我只是不知道为什么使用其他方式会忽略索引。
visible
必须在索引中 第一 。
INDEX(visible, views DESC, id DESC)
构建最优索引的一般规则是:
- 包括
WHERE
中用 = constant
测试的所有列。
- 然后是其他栏目。
更多详情:http://mysql.rjweb.org/doc.php/index_cookbook_mysql
您与 WHERE (shows.views, shows.id) < (0, 272990)
一起使用的 "row constructor" 可能存在 问题。在 5.7 之前,这基本上根本没有优化。
解决方法(5.7 之前的版本)是优化了您在评论中提到的复杂表达式。大概还在优化中:
WHERE (shows.views <= 0)
and not (shows.views = 0 and shows.id >= 272990)
8.0 在索引声明中引入了对 DESC
的尊重。
我担心优化器未能将这两个增强功能结合在一起来完成您正在寻找的东西。
请向我们展示您的尝试 EXPLAIN SELECT...
。特别注意 Key_len
.
即使没有 8.0,我也会推荐
INDEX(visible, views, id)
这种情况下,可以反向遍历索引来处理
WHERE visible = 0
AND ...
ORDER BY views DESC, id DESC
假设行构造函数问题已解决。
我有以下查询:
SELECT
shows.id,
shows.title,
shows.thumbnail,
shows.views,
shows.likes,
shows.dislikes,
shows.duration,
shows.hd,
shows.origin,
UNIX_TIMESTAMP(shows.upload_date) as upload_date
FROM
shows
WHERE
(shows.views, shows.id) < (0, 272990)
and shows.visible = 1
ORDER BY
shows.views DESC,
shows.id DESC
LIMIT
32
在 MySQL 8.0.15 中大约需要 0.8 秒。
我试过这样的索引:
CREATE INDEX views_desc_id_desc_visible ON shows (views desc, id desc, visible)
还有这样的:
CREATE INDEX views_desc_id_desc ON shows (views desc, id desc)
以及许多其他排列。我已经删除了它们并从头开始重做了很多次。 Visible 自身确实有一个索引。
当我进行 expain 时,我看到它仅在使用名为 views_desc_id_desc_visible 的键时执行 "Using where"。从查询中删除 visible 不会改变它的性能。删除两个 desc(因此:按视图排序,id)确实使它成为 0.0008 秒。
为什么这不会更快?
更新(从评论中复制)
SELECT shows.id, shows.title, shows.thumbnail, shows.views, shows.likes,
shows.dislikes, shows.duration, shows.hd, shows.origin,
UNIX_TIMESTAMP(shows.upload_date) as upload_date
FROM shows
WHERE (shows.views <= 0)
and not (shows.views = 0 and shows.id >= 272990)
and visible = 1
ORDER BY shows.views DESC, shows.id DESC
LIMIT 32
修复它。我只是不知道为什么使用其他方式会忽略索引。
visible
必须在索引中 第一 。
INDEX(visible, views DESC, id DESC)
构建最优索引的一般规则是:
- 包括
WHERE
中用= constant
测试的所有列。 - 然后是其他栏目。
更多详情:http://mysql.rjweb.org/doc.php/index_cookbook_mysql
您与 WHERE (shows.views, shows.id) < (0, 272990)
一起使用的 "row constructor" 可能存在 问题。在 5.7 之前,这基本上根本没有优化。
解决方法(5.7 之前的版本)是优化了您在评论中提到的复杂表达式。大概还在优化中:
WHERE (shows.views <= 0)
and not (shows.views = 0 and shows.id >= 272990)
8.0 在索引声明中引入了对 DESC
的尊重。
我担心优化器未能将这两个增强功能结合在一起来完成您正在寻找的东西。
请向我们展示您的尝试 EXPLAIN SELECT...
。特别注意 Key_len
.
即使没有 8.0,我也会推荐
INDEX(visible, views, id)
这种情况下,可以反向遍历索引来处理
WHERE visible = 0
AND ...
ORDER BY views DESC, id DESC
假设行构造函数问题已解决。