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)

构建最优索引的一般规则是:

  1. 包括 WHERE 中用 = constant 测试的所有列。
  2. 然后是其他栏目。

更多详情: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

假设行构造函数问题已解决。