2013-07-29 25 views
5

miałem tę kwerendę, aby rozpocząć się z:Jak zrobić JOINS szybciej?

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 

To zapytanie trwa 10ms wykonać.

Ale gdy dodaję prosty przyłączyć:

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 

Tym razem wykonać wzrosła o 11x. Teraz wykonanie wymaga około 120ms. Co ciekawe, po usunięciu LEFT JOIN klauzuli lub z ORDER BY id DESC, czas wraca do 10ms.

Jestem nowy w bazach danych, więc nie rozumiem tego. Dlaczego usunięcie którejś z tych klauzul przyspiesza to w górę? Jak mogę zachować go tak, jak jest, ale czy jest to szybsze?

Mam indeksy na spentits.user_id, follows.follower_id, follows.accepted i na primary ids dla każdej tabeli.

wyjaśnić:

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

Co zawiera EXPLAIN PLAN? –

+0

@DavidJashi zaktualizowany o EXPLAIN – 0xSina

Odpowiedz

2

Trzeba indeksu także na:

wishlist_items.spentit_id

Ponieważ łączą się tej kolumny

+0

Ups, zapomniałem go wymienić, ale mam to indeksowane. – 0xSina

0

lewym DOŁĄCZ jest łatwy y, aby wyjaśnić: Dokonano porównania wszystkich pozycji ze wszystkimi innymi wpisami. Warunki łączenia (w twoim przypadku: weź wszystkie wpisy po lewej i znajdź pasujące po prawej) zostaną zastosowane później. Więc jeśli Twój stały stół jest duży, zajmie to trochę czasu. Sugerowałbym, abyś pozbył się podkwerendy i wykonał trzy sprzężenia. Zacznij od najmniejszej tabeli, aby uniknąć dużych ilości danych.

+1

'Powstaje iloczyn krzyżowy wszystkich pozycji względem wszystkich innych wpisów' - To jest CROSS JOIN, a nie LEWY DOŁĄCZ –

+0

Również wykonanie 2 JOINS (dołączenie do podążania za podkomendą os) zabija wydajność. Wykonanie trwa około 350 ms. – 0xSina

0

W drugim przykładzie podselekcja działa dla każdego pliku utilits.user_id.

Jeśli piszesz jest podobny do tego, że będzie szybciej, ponieważ SUBSELECT biegnie raz:

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 

Jak widać SUBSELECT przeniesiony do OD-część zapytania i tworzy wyimaginowany tabel (lub widoku). Ta wymyślona tabela to widok śródliniowy.

Łączenia i widoki wiersza są szybsze za każdym razem niż podselekcja w części WHERE.

+0

Uzyskiwanie "Nieznanej kolumny" następuje po "w" gdzie klauzula " – 0xSina

+0

Masz rację. Jest błąd z "(" i operator IN nie pasuje do tabeli. – Shockergnomm

+0

Spróbuj to proszę: SELECT DISTINCT spentits * FROM 'spentits', (SELECT following_id FROM' follows' WHERE 'follows'.'follower_id' = '44' i' follows'.'accepted' = 1.) LUB spentits.user_id = '44') jako 'follow' LEFT JOIN wishlist_items NA wishlist_items.user_id = 44 i wishlist_items.spentit_id = spentits.id WHERE spentits.user_id = follow.following_id ORDER BY id DESC LIMIT 15 OFFSET 0 – Shockergnomm

Powiązane problemy