哪种方法会更快?
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;
【讨论】:
以上是关于哪种方法会更快?的主要内容,如果未能解决你的问题,请参考以下文章