我有这个查询开头:
SELECT DISTINCT spentits.*
FROM `spentits`
WHERE (spentits.user_id IN
(SELECT following_id
FROM `follows`
WHERE `follows`.`follower_id` = '44'
AND `follows`.`accepted` = 1)
OR spentits.user_id = '44')
ORDER BY id DESC
LIMIT 15 OFFSET 0
此查询执行10ms
。
但是,一旦我添加了一个简单的连接:
SELECT DISTINCT spentits.*
FROM `spentits`
LEFT JOIN wishlist_items ON wishlist_items.user_id = 44 AND wishlist_items.spentit_id = spentits.id
WHERE (spentits.user_id IN
(SELECT following_id
FROM `follows`
WHERE `follows`.`follower_id` = '44'
AND `follows`.`accepted` = 1)
OR spentits.user_id = '44')
ORDER BY id DESC
LIMIT 15 OFFSET 0
此执行时间增加11x
。现在需要执行120ms
。有趣的是,如果我删除LEFT JOIN
子句或 ORDER BY id DESC
,则时间会回到10ms
。
我是数据库的新手,所以我不明白这一点。为什么删除这些条款中的任何一个会加快11x
的速度?我怎样才能保持原样但速度更快?
我在每个表的spentits.user_id
,follows.follower_id
,follows.accepted
和primary ids
上都有索引。
说明:
1 PRIMARY spentits index index_spentits_on_user_id PRIMARY 4 NULL 15 Using where; Using temporary
1 PRIMARY wishlist_items ref index_wishlist_items_on_user_id,index_wishlist_items_on_spentit_id index_wishlist_items_on_spentit_id 5 spentit.spentits.id 1 Using where; Distinct
2 SUBQUERY follows index_merge index_follows_on_follower_id,index_follows_on_following_id,index_follows_on_accepted
index_follows_on_follower_id,index_follows_on_accepted 5,2 NULL 566 Using intersect(index_follows_on_follower_id,index_follows_on_accepted); Using where
答案 0 :(得分:2)
你也应该有索引:
wishlist_items.spentit_id
因为您正在加入该列
答案 1 :(得分:0)
LEFT JOIN很容易解释:所有条目与所有其他条目的交叉产品。然后应用连接的条件(在您的情况下:左侧的所有条目并在右侧找到拟合的条目)。因此,如果您的用过的表很大,那么服务器需要一些时间。建议你摆脱你的子查询并进行三次连接。从最小的表开始,以避免大量数据。
答案 2 :(得分:0)
在第二个示例中,subselect为每个spentits.user_id运行。
如果您这样写,它会更快,因为子选择运行一次:
SELECT DISTINCT spentits.*
FROM `spentits`, (SELECT following_id
FROM `follows`
WHERE `follows`.`follower_id` = '44'
AND `follows`.`accepted` = 1)
OR spentits.user_id = '44') as `follow`
LEFT JOIN wishlist_items ON wishlist_items.user_id = 44 AND wishlist_items.spentit_id = spentits.id
WHERE (spentits.user_id IN
(follow)
ORDER BY id DESC
LIMIT 15 OFFSET 0
如您所见,子选择移动到查询的FROM部分并创建一个虚构的tabel(或视图)。 这个虚构的表格是一个内联视图。
JOIN和内联视图每次都比WHERE部分中的子选择更快。