【发布时间】:2013-06-04 15:38:07
【问题描述】:
这是一个查询:
SELECT DISTINCT
spentits.*,
username,
(SELECT count(*) from likes where likes.spentit_id = spentits.id) as like_count,
(SELECT count(*) from comments where comments.spentit_id = spentits.id) as comment_count,
(SELECT count(*) from wishlist_items where wishlist_items.spentit_id = spentits.id) as wishlist_count,
(case when likes.id is null then 0 else 1 end) as is_liked_by_me,
(case when wishlist_items.id is null then 0 else 1 end) as is_wishlisted_by_me
FROM spentits
LEFT JOIN users ON users.id = spentits.user_id
LEFT JOIN likes ON likes.user_id = 9 AND likes.spentit_id = spentits.id
LEFT JOIN wishlist_items ON wishlist_items.user_id = 9 AND wishlist_items.spentit_id = spentits.id
WHERE spentits.user_id IN
(SELECT follows.following_id
FROM follows
WHERE follows.follower_id = 9)
ORDER BY id DESC
LIMIT 15;
这平均需要43ms 才能执行。现在另一个查询(如下)没有 where 子句,更不用说第二个 SELECT 子查询的执行速度要慢 5 倍(240ms)!
SELECT DISTINCT
spentits.*,
username,
(SELECT count(*) from likes where likes.spentit_id = spentits.id) as like_count,
(SELECT count(*) from comments where comments.spentit_id = spentits.id) as comment_count,
(SELECT count(*) from wishlist_items where wishlist_items.spentit_id = spentits.id) as wishlist_count,
(case when likes.id is null then 0 else 1 end) as is_liked_by_me,
(case when wishlist_items.id is null then 0 else 1 end) as is_wishlisted_by_me
FROM spentits
LEFT JOIN users ON users.id = spentits.user_id
LEFT JOIN likes ON likes.user_id = 9 AND likes.spentit_id = spentits.id
LEFT JOIN wishlist_items ON wishlist_items.user_id = 9 AND wishlist_items.spentit_id = spentits.id
ORDER BY id DESC
LIMIT 15;
为什么?第二个查询不应该快得多,因为没有条件,没有第二个查询。数据库需要做的就是选择最后 15 条记录,与第一个相比,它需要在执行子查询后扫描每条记录并检查 id 是否包含在其中。我真的很困惑,一个应该执行得更快的查询实际上却慢了 5 倍。
【问题讨论】:
-
存在与统计和元数据相关的执行路径,请为两者执行
explain plan。按 id 过滤可能会在没有行的表上执行跳过,当您不按该 id 过滤时,会处理行。 -
难道不是因为第一个有 where 子句会带回更少的行吗?
-
@anna 他们都有 LIMIT 15
-
第一个版本将行数限制为小得多,因此
order by的工作量要少得多。 -
应该是处理不同行数的顺序