尝试使用corollated子查询优化此查询
SELECT g.*, g.instaLikes + ( SELECT COUNT( * ) FROM gallery_likes AS l WHERE l.gallery_id = g.id ) AS likes
FROM gallery AS g
WHERE ( STATUS = 'approved' )
ORDER BY g.moderated_at DESC , g.id ASC
没有子查询的SELECT非常快,当我尝试LEFT JOIN时它更慢。
SELECT g.*, (g.instaLikes + COUNT( l.id ) ) AS likes
FROM gallery AS g
LEFT JOIN gallery_likes AS l ON ( g.id = l.gallery_id )
WHERE ( STATUS = 'approved)
GROUP BY g.id
ORDER BY g.moderated_at DESC , g.id ASC
似乎最快的选项是单独执行查询,然后在PHP循环中将字段一起添加,因为我可以运行子查询一次,而不是在库中运行n次。
目前gallery中有2000行,gallery_likes中有15000行。我认为我还不需要进行优化,因为这些数字似乎很低,但是第一个查询需要20-30秒而LEFT JOIN需要100秒以上!
答案 0 :(得分:1)
进行单独的查询并在PHP中加入数据并不是一个坏主意。但是如果你想在SQL中做同样的事情,你可以。您可以像查询表一样处理查询(即连接它),它们称为派生表。这通常是优化这些类型查询的更快捷方式。
SELECT g.*, g.instaLikes + l.c
FROM gallery AS g
LEFT JOIN (
SELECT gallery_id, COUNT( * ) c FROM gallery_likes GROUP BY gallery_id
) AS l ON g.id=l.gallery_id
WHERE ( STATUS = 'approved' )
ORDER BY g.moderated_at DESC , g.id ASC
这是对来自gallery_likes的所有记录进行分组,这可能非常低效。所以你应该添加一些过滤器。如果子选择(派生表)加入库并使用与外部查询相同的过滤器,则为事件。这几乎就像您的第二个查询,但它在加入之前对数据进行分组。而不是加入然后分组。
当您需要加入摘要数据(即分组依据)时,这通常是一个很好的解决方案,但有时它可能效率低下。您通常可以通过EXPLAIN告诉。