我有以下查询:
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)
以及许多其他排列。我已经删除了它们,并从头开始多次重做。可见的确具有索引。
当我进行解释时,我看到它仅在使用名为views_desc_id_desc_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
修复它。我只是不知道为什么使用这种方式会忽略索引。
答案 0 :(得分:2)
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)
一起使用的“行构造器”存在可能问题。直到5.7才根本没有优化。
解决方法(5.7之前)是优化了您在Comment中提到的复杂表达式。它可能仍处于优化状态:
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
假设行构造器问题已解决。