数据库
首页 > 数据库> > mysql – select vs left join中的子查询

mysql – select vs left join中的子查询

作者:互联网

通常,我必须在查询中返回某些行的计数,以获取其他不相关的行.

例如A表用户表格查看和表格图片

User:
id
nickname

Review:
id
to_user_id
from_user_id
rating

Picture:
id:
user_id
url

假设我想在一个查询中检索“给定”userId的昵称所有其图片网址以及审核该用户的人数.

我在做这个查询时想到的第一个简单的方法是:

SELECT
  u.nickname
  (SELECT count(*) FROM review WHERE to_user_id = u.id) as reviewCount,
  p.url
FROM user
LEFT JOIN picture ON p.user_id = u.id
WHERE 
  u.id = 1

另一种方法是在没有该子选择的情况下,并在右侧user_id上加入审阅表

SELECT 
 u.nickname,
 r.reviewCount,
 p.url
FROM user u 
LEFT JOIN (
    SELECT to_user_id, count(*) reviewCount FROM review GROUP BY to_user_id
 ) r ON r.to_user_id = u.id
LEFT JOIN picture ON p.user_id = u.id 
WHERE u.id = 1;

我不是db查询性能和调优方面的专家.有人可以解释我,如果解决方案比另一个更好吗? (或者,如果还有其他更好的解决方案)?

编辑:
对不起忘了提.我正在使用最新的MySQL

解决方法:

您没有指定使用的RDBMS.我在这里写的大多数应该是相当独立的,但我主要在MySQL中有经验,所以也许不同的系统允许其他一些优化.

(SELECT count(*)FROM review WHERE to_user_id = u.id)作为reviewCount是一个从属子查询 – 它将在结果中的每一行执行.即使一次执行速度很快,也可能成千上万的执行速度变慢.

JOIN中的一个是派生表 – 它只执行一次并实现为临时表,然后将其连接到其他表.如果查询速度很快(可以使用index on(to_user_id)),那就很好了.但在这种情况下,即使对于未在结果中显示的用户,也会计算计数.但是……你可以在那里推送条件(to_user_id = 1而不是GROUP BY).

但是为了使事情变得不那么简单,在新版本中存在一些优化.通过在MariaDB 10(和IIRC MySQL 5.7中使用子查询缓存,但我没有验证),可以更快地使从属子查询更快.这意味着在您的情况下,结果中的所有行都有u.id = 1 – > to_user_id = 1,子查询实际只执行一次,然后将使用缓存的结果.如果可以,两个版本之间的差异将是最小的.

我个人更喜欢你的第二个版本,但有些情况下第一个版本会更快 – 我曾经有一个查询,其中不可能简单地限制JOINED子查询中的行正确的方式,但切换到从属子查询实际上只读取了几个独特的组合.

标签:mysql-5-7,query-performance,mysql,optimization
来源: https://codeday.me/bug/20190806/1600636.html