我有一个选择从卖家那里得到客户跟随的产品。
这个产品有喜欢,评论,需要计数喜欢,需要计算评论和展示另一件事。
我有where user in
来获取用户关注的客户。
问题是,这个选择需要一段时间,我想知道我是否能以某种方式改进它。我的所有ID都是键。
select c.nome, p.foto, c.user, p.user, p.id, p.data, p.titulo, p.youtube, pp.foto, count(DISTINCT likes.user) as likes_count, count(distinct comentarios.id) as comentarios_count, count(DISTINCT l2.user) as count2
from products p
join users c on p.user=c.id
left join profile_picture pp on p.user = pp.user
left join likes on likes.post = p.id
left join comentarios on comentarios.foto = p.id and comentarios.delete = 0
left join likes l2 on l2.post = p.id and l2.user = ?
where (p.user in (select following from following where user =? and block=0) or p.user=?) and p.delete='0'
group by p.id
order by p.id desc limit ?
答案 0 :(得分:4)
使用delete和user列在 products 表中应用索引(使用复合索引)。
应用适当的索引用户表
SELECT c.nome, p.foto, c.user, p.user, p.id, p.data, p.titulo, p.youtube, pp.foto, COUNT(DISTINCT likes.user) AS likes_count, COUNT(DISTINCT comentarios.id) AS comentarios_count, COUNT(DISTINCT l2.user) AS count2
FROM products p
LEFT JOIN users c ON p.user=c.id
LEFT JOIN profile_picture pp ON p.user = pp.user
LEFT JOIN likes ON likes.post = p.id
LEFT JOIN comentarios ON comentarios.foto = p.id AND comentarios.delete = 0
LEFT JOIN likes l2 ON l2.post = p.id AND l2.user = ?
WHERE c.id IS NOT NULL AND (p.user IN (SELECT following FROM following WHERE USER =? AND block=0) OR p.user=?) AND p.delete='0'
GROUP BY p.id
ORDER BY p.id DESC LIMIT ?
使用上述查询可以为您提供更好的性能
答案 1 :(得分:3)
TL; DR
根据您的解释,您认为products
上没有索引键(user, delete, id)
。这可能是当前查询的最大爆炸。
我要假设,因为你问这个你不知道EXPLAIN
,即使你做了,也许很难解析方向继续前进如果你读过它就做
简而言之,假设您没有要处理的主要存储/内存问题,并且可以在表中添加索引,我建议您需要在表上添加以下索引:
products
(user, delete, id)
的综合索引
likes
(post, user)
的综合索引
comentarios
上的表(foto, delete)
的综合索引。 我讨厌保留词语后的栏目(如删除)!!!! following
(user, block)
的综合索引
这会使连接有效但不是100%覆盖,在这种情况下,您可能不希望从您的选择值。
可能已经存在符合上述要求的现有索引,任何以上述值(按照确切顺序)开头的索引都将足够好。例如,如果您在likes
上拥有表(post, user, some_other_column)
的索引,则它已经提供了我在(post, user)
上建议索引所需的所有内容。关键是需要的值必须完全相同。
现在有很多细微的索引编制和很多你想要学习的东西,但这应该可以解除你的工作。
只是抛出一些额外的东西:
comentarios.foto
如果确实是产品表中的id,则会更好地命名为comentarios.products_id
。这种清晰的命名将有助于防止错误/错误,提高编写新查询的效率,并最大限度地减少未来开发人员试图理解您的架构的理智。EXPLAIN
。只需在查询之前添加关键字EXPLAIN
并运行它。结果显示了查询引擎最初计划执行查询的内容(实际上可能会在执行期间发生偏差,但通常会非常适合)。从中您可以看到可能需要索引来改善执行。答案 2 :(得分:1)
除了Ray对索引的出色建议之外,我还建议您尝试将IN
重写为EXISTS
。优化者很少永远不会自己做,但它通常更便宜。所以
p.user in (select following from following where user =? and block=0)
应该阅读
exists (select * from following where user = ? and block = 0 and following = p.user)
在following (user, following, block)
或following (following, user, block)
上创建综合索引,以支持上述EXISTS
的子查询。这里很难猜出user
和following
中的哪一个具有更好的选择性。他们可能非常相似,所以两个订单都应该这样做。可以肯定的是,检查哪个列在表中具有更多不同的值并将其放在第一个。