sql—提高大型mysql select性能

bvn4nwqk  于 2021-06-25  发布在  Mysql
关注(0)|答案(3)|浏览(322)

我有一个选择,以获得产品从卖方,客户遵循。这个产品有喜欢,评论,需要计数喜欢,需要计数评论和显示其他东西。我有一个 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 ?

解释:

jutyujz0

jutyujz01#

除了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 具有较好的选择性。它们可能很相似,所以两个命令都应该这样做。要确定,请检查表中哪个列具有更多不同的值,并将其放在第一位。

brtdzjyr

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 在您的查询和运行它之前。结果显示了查询引擎最初计划执行查询的内容(在执行过程中可能会出现偏差,但通常非常准确)。从这里您可以看到哪里可能需要索引来改进执行。

up9lanfz

up9lanfz3#

使用delete和user列在products表中应用索引(使用复合索引)。
应用适当的索引ind users表

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 ?

使用上述查询可能会给您带来更好的性能

相关问题