2013-07-29 11 views
5

私はでスタートするには、このクエリを持っていた:JOINSをより速くするには?

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かかります。

しかし、私は単純結合追加すると:これは11x増加した時間を実行

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 

。今すぐ実行するには、120msがかかります。面白いのは、LEFT JOINという句またはのうちORDER BY id DESCのいずれかを削除すると、時間は10msに戻ります。

私はデータベースに新しいので、私はこれを理解していません。なぜこれらの句のいずれかを削除すると、それをスピードアップするのはなぜですか?11x?そして私はそれをそのまま保つことができますが、それをより速くすることができますか?

私はそれぞれの表のspentits.user_id,follows.follower_id,follows.acceptedおよびprimary idsにインデックスを持っています。

はEXPLAIN:

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 
+1

EXPLAIN PLANとは何ですか? –

+0

@DavidJashiがEXPLAINで更新されました – 0xSina

答えて

2

をあなたはまた、上のインデックスを持つ必要があります:あなたは、その列

+0

おっと、私はそれをリストするのを忘れましたが、インデックスを作成しました。 – 0xSina

0

LEFT上で参加しているので

をwishlist_items.spentit_id JOINは簡単です説明する:すべてのエントリーと他のすべてのエントリーのクロス積が作られる。結合の条件(あなたの場合:左のすべての項目を取り、右の項目を見つける)が後で適用されます。だから、あなたの費やしテーブルが大きければ、サーバはしばらく時間がかかるでしょう。サブクエリを取り除き、3つの結合を行うことをお勧めします。大量のデータを避けるために、最小のテーブルから始めます。

+1

'他のすべてのエントリとのクロスプロダクトが作成されました。 - これは、LEFT JOINではなくCROSS JOINです。 –

+0

また、2つのJOINS(osサブクエリではなく、実行には約350msかかります。 – 0xSina

0

第2の例では、すべてのspendits.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部分の副選択よりも高速です。

+0

'不明な列'を取得する 'in' where句 '' – 0xSina

+0

あなたは正しいです。 '('でIN演算子がタブと一致しないというミスがあります。 – Shockergnomm

+0

これをしてくださいしてみてください。 はDISTINCT spentitsをSELECT * spentits' 'から(' follows' WHERE 'follows'.'follower_id' = '44' と' follows'.'accepted' = 1 FROM following_id を選択します。 ) OR spentits.user_id = '44')ID DESC LIMIT 15によって 'follow' LEFT wishlist_items.user_id ON wishlist_itemsをJOIN = 44 AND wishlist_items.spentit_id = spentits.id WHERE spentits.user_id = follow.following_id 順序とOFFSET 0 – Shockergnomm

関連する問題