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
开头。 (我目前没有看到。)
我在 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
开头。 (我目前没有看到。)