mysql - 预过滤查询
问题描述
我正在尝试优化一个需要很长时间的查询,我无法向数据库添加任何新索引,但我找到了一种将执行时间缩短一半的方法。解决方案是仅使用一些 WHERE 条件对查询进行预过滤,返回 id 并在这些 id 上运行其余条件。我想知道是否可以在没有往返的情况下做到这一点
原始查询的最小示例(不是实际查询,而是相同的想法):
SELECT
COUNT(*) as total
FROM
my_db.bananas AS b,
my_db.bananas_specs as s
WHERE
b.created BETWEEN '2021-01-01 00:00:00' AND '2022-01-01 00:00:00'
AND b.gone_bad = false
AND b.id = s.id
AND s.is_cool = true
我的新查询一起运行了一半的时间:
SELECT
GROUP_CONCAT(id SEPARATOR ', ') as ids
FROM
my_db.bananas
WHERE
created BETWEEN '2021-01-01 00:00:00' AND '2022-01-01 00:00:00'
和
SELECT
COUNT(*) as total
FROM
my_db.bananas AS b,
my_db.bananas_specs as s
WHERE
b.id in (...result of first query)
AND b.gone_bad = false
AND b.id = s.id
AND s.is_cool = true
我知道 mysql 中有变量,并且它可以在单个查询中运行多个 select 语句,因为谷歌告诉我它是这样,但我无法让它工作,php 给我的错误消息不是很有帮助。本质上,如何在单个查询中将后两个查询作为单独的选择语句执行?
解决方案
with 语句对于优化代码可读性问题非常有用 - 在加入第二个表之前选择基础数据可以改善,但不会显着。
只计算一列可以提高性能,而不是计算整个数据集
例如
with cte_bananas as (
SELECT id, created, gone_bad
from my_db.bananas
where created BETWEEN '2021-01-01 00:00:00' AND '2022-01-01 00:00:00'
) -- end with cte_bananas
select count(1) as Total
from cte_bananas b
inner join my_db.bananas_specs as s
on s.id = b.id
where b.gone_bad = false
and s.is_cool = true
由于您的查询是一个片段,因此这里可能需要进行一些实验。
推荐阅读
- jsf - javax.el.PropertyNotWritableException:类“java.util.HashMap$Node”没有可写属性“值”
- json - 如何将此 API get() 结果转换为 JSON 对象?
- gradle - gradle:应用程序运行参数无法传递系统属性
- azure-devops - 如何允许用户向我的公共存储库提交问题?
- python-3.x - How to write a function using for and if
- c# - 如果值超出类型边界,如何本地化值类型(ushort)属性的默认验证消息?
- python - Plotting xscale with negative powers of 10 in matplotlib
- bash - 从包含 ip 地址和其他字母数字的字符串中提取 ip 地址
- php - Why comparing Strings in MySQL query is not working
- oauth-2.0 - Oauth2 供个人使用