2

我有以下查询:

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 本身确实有一个索引。

当我进行解释时,我看到它只在使用名为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

修复它。我只是不知道为什么以其他方式使用会忽略索引。

4

1 回答 1

3

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)。在 5.7 之前,这基本上根本没有优化。

解决方法(5.7 之前)是优化了您在评论中提到的复杂表达式。它可能仍在优化:

WHERE      (shows.views <= 0)
  and  not (shows.views  = 0 and shows.id >= 272990)

8.0DESC在索引声明中引入了尊重。

我担心优化器未能将这两个增强功能放在一起来完成您正在寻找的事情。

请向我们展示EXPLAIN SELECT...您的尝试。尤其看Key_len

即使没有 8.0,我也会推荐

INDEX(visible, views, id)

在这种情况下,可以反向遍历索引来处理

WHERE visible = 0
  AND ...
ORDER BY views DESC, id DESC

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

于 2019-04-28T16:15:47.840 回答