哪种方法会更快?

Posted

技术标签:

【中文标题】哪种方法会更快?【英文标题】:Which approach will be faster? 【发布时间】:2014-08-21 16:34:19 【问题描述】:

我必须选择用户列表,对于每个用户,我必须返回他是否被关注的信息(当前/请求用户)。现在我这样查询:

SELECT 
   "User"."name", 
   EXISTS(
      SELECT * FROM "Followings" f WHERE f."FollowedId" = "User"."id" AND f."FollowerId" = 123
   )::boolean AS "isFollowed"
FROM "Users" AS "User" 
ORDER BY "User"."createdAt" 
LIMIT 15

注意:123 是检索用户列表的用户 id。

制作这样的嵌套 SELECT 是个好主意吗?这种查询的性能如何?

我的第二个想法就是制作"Users" LEFT JOIN "Followings" - 如果加入了关注,则关注用户。哪种方法会更好?

【问题讨论】:

在大多数情况下,您应该使用 JOINS 源:***.com/questions/2577174/join-vs-sub-query 这是一个 mysql 问题(和答案)。这是 PostgreSQL。根据我的经验,子查询的性能很大程度上取决于引擎优化它们的能力。 Firebird 非常适合子查询。但我对 PostgreSQL 的了解还不够,无法回答这个问题。 这里不用讨论速度,查询不同,结果也会不同。 EXISTS 版本将始终为每个用户生成一个元组,LEFT JOIN至少为每个用户生成一个元组(假设 1:N 关系) @LucaB。这不是其中一种情况,您的链接答案不合适。 糟糕的是我完全错过了 postgresql 标签 【参考方案1】:

是的,您的查询是关于最佳的。我只是简化并删除了多余的演员:

SELECT name
     , EXISTS (
          SELECT 1 FROM "Followings" f
          WHERE  f."FollowedId" = u."id"
          AND    f."FollowerId" = 123
          ) AS "isFollowed"
FROM  "Users" u
ORDER  BY "createdAt" 
LIMIT  15;
::boolean 的强制转换是多余的,因为EXISTS 已经返回了boolean

带有LEFT JOIN 的替代形式将执行大致相同或更慢,但更复杂并且还取决于("FollowedId", "FollowerId") 是唯一的,或者您可以获得多行,这可能会与您的LIMIT 混淆,所以您需要添加GROUP BY。假设唯一对:

SELECT u.name
     ,(f."FollowedId" IS NOT NULL) AS "isFollowed"
FROM  "Users" u
LEFT  JOIN "Followings" f ON f."FollowedId" = u."id"
                         AND f."FollowerId" = 123
ORDER  BY u."createdAt" 
LIMIT  15;

【讨论】:

以上是关于哪种方法会更快?的主要内容,如果未能解决你的问题,请参考以下文章

哪种方法更快?

矢量访问速度,哪种方法更快?

哪种检查 NSDictionary 是不是包含特定键的方法更快?

哪种方法更快,表示:服务器端渲染与客户端渲染

哪种方式更快? [关闭]

哪种方法可以更快地使用 PHP/Laravel 从 MySQL/MariaDB 获取所有 POI