Mysql查询性能多个and or条件

Mysql query performance multiple and or conditions

我在 mysql 中有这个查询,但性能很差。

select `notifiables`.`notification_id` 
from `notifiables` 
where `notifiables`.`notification_type` in (2, 3, 4) 
  and (    (    `notifiables`.`notifiable_type` = 16 
            and `notifiables`.`notifiable_id` = 53642) 
        or (    `notifiables`.`notifiable_type` = 17 
            and `notifiables`.`notifiable_id` = 26358) 
        or (    `notifiables`.`notifiable_type` = 18 
            and `notifiables`.`notifiable_id` = 2654)) 
order by `notifiables`.`id` desc limit 20

是否可以通过任何方式优化此查询。请帮忙 这个 table 有 2M 行。搜索最多需要 1-4 秒

更新索引和解释select

你可以根据你想要的数据制作不同种类的“VIEW”,然后加入它们。

使用下一个语法:

SELECT notification_id
FROM notifiables 
WHERE notification_type IN (2, 3, 4) 
  AND (notifiable_type, notifiable_id) IN ( (16, 53642), (17, 26358), (18, 2654) )
ORDER BY id DESC LIMIT 20

通过(notification_type, notifiable_type, notifiable_id)(notifiable_type, notifiable_id, notification_type)创建索引(取决于单独的条件选择性)。

或创建覆盖索引((notification_type, notifiable_type, notifiable_id, notification_id)(notifiable_type, notifiable_id, notification_type, notification_id))。

可能的解决方案:

  • OR变成UNION(见@hongnhat)

  • 行构造函数(参见@Akina)

  • 添加

      AND notifiable_type IN (16, 17, 18)
    
  • 索引提示。我不喜欢这个,因为它往往弊大于利。但是,优化器错误地选择了 PRIMARY KEY(id)(因为 ORDER BY 而不是某些过滤器,根据 Cardinality 应该非常好。

  • INDEX(notification_type, notifiable_type, notifiable_id, id, notification_id) -- 这是“覆盖”,这很有帮助,因为索引可能比数据集 'smaller'。添加此索引时,DROP 您当前的 INDEX(notification_type) 因为它会分散优化器的注意力。

  • VIEW不太可能提供帮助。

更多

试一试:将其添加到 WHERE

的开头
WHERE notifiable_id IN ( 53642, 26358, 2654 ) 
  AND ... (all of what you have now)

并确保 INDEX notifiable_id 开头。 (我目前没有看到。)