我有以下查询:
SELECT *
FROM products
INNER JOIN product_meta
ON products.id = product_meta.product_id
JOIN sales_rights
ON product_meta.product_id = sales_rights.product_id
WHERE ( products.categories REGEXP '[[:<:]]5[[:>:]]' )
AND ( active = '1' )
AND ( products.show_browse = 1 )
AND ( product_meta.software_platform_mac IS NOT NULL )
AND ( sales_rights.country_id = '240'
OR sales_rights.country_id = '223' )
GROUP BY products.id
ORDER BY products.avg_rating DESC
LIMIT 0, 18;
在省略ORDER BY
部分的情况下运行查询,查询在〜90ms内运行,ORDER BY
部分,查询需要〜8s。
我浏览了SO并且发现原因可能是在返回所有数据之前正在执行排序,而是我们应该在结果集上运行ORDER BY
? (见这篇文章:Slow query when using ORDER BY)
但我无法弄清楚我如何做到这一点的明确方式?
答案 0 :(得分:1)
我在SO周围浏览并找到了原因 在返回所有数据之前执行排序,以及 相反,我们应该在结果集上运行ORDER BY?
我发现很难相信,但如果这确实是问题,我认为你需要做这样的事情。 (注意我把它放在哪里。)
select * from
(
SELECT products.id, products.avg_rating
FROM products
INNER JOIN product_meta
ON products.id = product_meta.product_id
JOIN sales_rights
ON product_meta.product_id = sales_rights.product_id
WHERE ( products.categories REGEXP '[[:<:]]5[[:>:]]' )
AND ( active = '1' )
AND ( products.show_browse = 1 )
AND ( product_meta.software_platform_mac IS NOT NULL )
AND ( sales_rights.country_id = '240'
OR sales_rights.country_id = '223' )
GROUP BY products.id
) as X
ORDER BY avg_rating DESC
LIMIT 0, 18;
此外,编辑您的问题并添加指向该建议的链接。我想很多人都会从阅读中受益。
其他可能不相关的问题
WHERE子句中使用的每一列都应该以某种方式编入索引。对于此特定查询,多列索引可能会执行更好的 。
列products.categories似乎存储了使用正则表达式过滤的多个值。在单个列中存储多个值通常是个坏主意。
MySQL's GROUP BY
is indeterminate。使用GROUP BY
的标准SQL语句可能返回的行数较少,并且可能会更快地返回它们。
答案 1 :(得分:0)
如果可以,您可能希望索引ID列,以便查询更快地运行。这是一个DBA级解决方案,而不是SQL解决方案 - 调整数据库将有助于整体性能。
答案 2 :(得分:0)
此查询实例中的问题是,在查询中使用GROUP BY
和ORDER BY
,如果GROUP BY
和{{1},MySQL无法使用索引表达式不同。
相关阅读: