我最近一直在尝试优化我们的数据库以提高其可扩展性,但遇到了一些我无法进一步优化的问题,但感觉应该有一些东西我可以做得更好。我目前有:
SELECT b.id, b.title, COUNT(p.id) AS count
FROM brands b
LEFT JOIN products p ON b.id = p.brand_id
WHERE p.status = 'Accepted'
GROUP BY b.id
我可能会添加额外的 WHERE
子句来进一步过滤产品,因此我排除了在每个品牌记录上保留已接受产品的维护计数(这可能是一个不好的方法无论如何)。
这些表为 MyISAM
、b.id
、p.brand_id
和 p.status
建立了索引。大约 500,000 种产品和大约 1,000 个品牌,它的耗时约为 2.5 秒。我可以做一些更好的事情来获取包含产品数量的品牌列表,或者对于我想要实现的目标来说,这个时间框架实际上相当合理吗?
最佳答案
对于此查询:
SELECT b.id, b.title, COUNT(p.id) AS count
FROM brands b LEFT JOIN
products p
ON b.id = p.brand_id
WHERE p.status = 'Accepted'
GROUP BY b.id;
我建议对产品(状态,brand_id)
和品牌(id,标题)
建立索引。
但是,您的 WHERE
正在将 LEFT JOIN
转换为 INNER JOIN
,因此您应该对此进行具体说明。也许你真的想要:
SELECT b.id, b.title, COUNT(p.id) AS count
FROM brands b LEFT JOIN
products p
ON b.id = p.brand_id AND p.status = 'Accepted'
GROUP BY b.id;
这将返回计数为零的品牌。原始版本没有(尽管 LEFT JOIN
表明这是您的意图)。
如果是这样,那么相关子查询可以获得更好的性能:
SELECT b.id, b.title,
(SELECT COUNT(*)
FROM products p
WHERE b.id = p.brand_id AND p.status = 'Accepted'
) AS count
FROM brands b;
此查询的最佳索引是products(brand_id, status)
。
关于php - MySQL JOIN 具有 COUNT 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32269233/