MySQL 8的复合索引下降

时间:2019-04-21 02:03:57

标签: mysql indexing 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)

以及许多其他排列。我已经删除了它们,并从头开始多次重做。可见的确具有索引。

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

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

1 个答案:

答案 0 :(得分:2)

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之前)是优化了您在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

假设行构造器问题已解决。