我有一个选择,以获得产品从卖方,客户遵循。这个产品有喜欢,评论,需要计数喜欢,需要计数评论和显示其他东西。我有一个 where user in
获取用户关注的客户。
问题是,这个选择需要一段时间,我想知道我是否可以改进它。我所有的身份证都是钥匙。
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 ?
解释:
3条答案
按热度按时间jutyujz01#
除了ray对索引的出色建议之外,我还进一步建议尝试重写
IN
到一个EXISTS
. 优化器很少能做到这一点,但它通常更便宜。所以应该读
.
在上创建复合索引
following (user, following, block)
或者following (following, user, block)
支持上述子查询EXISTS
. 在这里很难猜测user
以及following
具有较好的选择性。它们可能很相似,所以两个命令都应该这样做。要确定,请检查表中哪个列具有更多不同的值,并将其放在第一位。brtdzjyr2#
热释光;博士
根据您的解释,看起来您没有索引键
products
在(user, delete, id)
. 这可能是当前查询的最大爆炸。我想既然你问这个你就不知道了
EXPLAIN
即使你读了,可能也很难分析出方向,如果你真的读了它的话,该怎么办。简而言之,假设您没有要处理的主要存储/内存问题,并且可以向表中添加索引,我建议您需要在表中设置以下索引:
表的综合索引
products
在(user, delete, id)
表的综合索引likes
在(post, user)
表的综合索引comentarios
在(foto, delete)
. 我讨厌以保留字命名的列(比如delete)!!!!表的综合索引
following
在(user, block)
这将使连接有效,但不是100%覆盖,在这种情况下,从您选择的值来看,这可能不理想。可能已经存在符合上述条件的索引,任何以表中的上述值(按确切顺序)开头的索引都足够了。例如,如果有表的索引
likes
在(post, user, some_other_column)
它已经提供了我的索引建议所需要的一切(post, user)
. 关键是需要从中输入的值的顺序必须完全相同。现在索引有很多细微的差别,还有很多你想学的东西,但这应该会解除你工作的障碍。
只需抛出一些额外的东西:
您应该在与外键相关的表和列之后命名它们。例如
comentarios.foto
最好叫这个名字comentarios.products_id
如果它确实是products表中的id。这种清晰的命名将有助于防止错误/错误,提高编写新查询的效率,并最大限度地减少未来开发人员试图摸索模式时的理智损失。正如一些评论者所提到的,学习如何阅读mysql
EXPLAIN
关于你的问题。只需添加关键字EXPLAIN
在您的查询和运行它之前。结果显示了查询引擎最初计划执行查询的内容(在执行过程中可能会出现偏差,但通常非常准确)。从这里您可以看到哪里可能需要索引来改进执行。up9lanfz3#
使用delete和user列在products表中应用索引(使用复合索引)。
应用适当的索引ind users表
使用上述查询可能会给您带来更好的性能