2013-12-09 17 views
5

nie jestem genialny jeśli chodzi o dzieje poza podstawy z MySQL, jednak staram się optymalizować zapytania:Indeksy i optymalizacja

SELECT DATE_FORMAT(t.completed, '%H') AS hour, t.orderId, t.completed as stamp, 
     t.deadline as deadline, t.completedBy as user, p.largeFormat as largeFormat 
    FROM tasks t 
    JOIN orders o ON o.id=t.orderId 
    JOIN products p ON p.id=o.productId 
    WHERE DATE(t.completed) = '2013-09-11' 
    AND t.type = 7 
    AND t.completedBy IN ('user1', 'user2') 
    AND t.suspended = '0' 
    AND o.shanleys = 0 
    LIMIT 0,100 

+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+ 
| id | select_type | table | type | possible_keys    | key  | key_len | ref    | rows | Extra  | 
+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+ 
| 1 | SIMPLE  | o  | ref | PRIMARY,productId,shanleys | shanleys | 2  | const   | 54464 | Using where | 
| 1 | SIMPLE  | p  | eq_ref | PRIMARY     | PRIMARY | 4  | sfp.o.productId |  1 |    | 
| 1 | SIMPLE  | t  | ref | NewIndex1     | NewIndex1 | 5  | sfp.o.id  |  6 | Using where | 
+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+ 

Przed niektórych indeksów dodano było wykonanie pełne skanowanie tabeli zarówno na stole p, jak i na stole o.

Zasadniczo, myślałem, że MySQL będzie:

granica wzdłuż rzędów z tabeli zadań z klauzul WHERE (powinno być 84 rzędów bez sprzężeń)

następnie przejść tabeli zamówień na produkty tabela, aby uzyskać flagę (largeFormat).

Moje pytanie brzmi, dlaczego MySQL sprawdza nawet 50000 wierszy, gdy szuka tylko 84 różnych identyfikatorów i czy mogę zoptymalizować zapytanie?

Nie mogę dodać nowych pól ani nowych tabel.

Z góry dziękuję!

+0

To wygląda całkiem nieźle. Czy wydajność jest problemem? – Strawberry

+0

Użyłem odpowiedzi @ DRapp poniżej, w zasadzie za pomocą funkcji daty spowodowałam, że wygląd wziął 7,98 s, a teraz zajmuje 0,04 s. : p –

Odpowiedz

5

SQL musi pracować na dostępnych indeksów jak najlepiej zakwalifikować kwerendy

musiałbym indeks związku na (typ, zawieszone, completedby, zakończone) dopasować kryteria masz ... swoich zamówień oraz tabele produktów wyglądają dobrze z ich istniejącymi indeksami.

SELECT 
     DATE_FORMAT(t.completed, '%H') AS hour, 
     t.orderId, 
     t.completed as stamp, 
     t.deadline, 
     t.completedBy as user, 
     p.largeFormat as largeFormat 
    FROM 
     tasks t 
     JOIN orders o 
      ON t.orderId = o.id 
      AND o.shanleys = 0 
      JOIN products p 
       ON o.productId = p.id 
    WHERE 
      t.type = 7 
     AND t.suspended = 0 
     AND t.completedBy IN ('user1', 'user2') 
     AND t.completed >= '2013-09-11' 
     AND t.completed < '2013-09-12' 
    LIMIT 
     0,100 

Podejrzewam, że zawieszona jest flaga i jest numeryczne (int) na podstawie, a jeśli tak, pozostawić kryteria jako liczbowe, a nie ciąg owijając w „0” cudzysłowie.

dla pól datetime, jeśli próby zastosowania funkcji do niego, to nie mogę wykorzystać indeks dobrze ... więc, jeśli tylko dbają o jeden dzień (lub zakres w innych zapytań), Wskazówka mam pole datetime> = '2013-09-11', co jest implikowane o 00:00:00, ORAZ polu datetime jest MNIEJ NIŻ "2013-09-12", które pozwala do 23:59:59 w dniu 2013- 09-11 , który jest cały dzień, a indeks może z niego skorzystać.

+1

Wow! To ogromna poprawa wydajności od 7,98 s do 0,04 s. Dziękuję bardzo i dziękuję za wyjaśnienie! –

+2

@RossWilson, nie ma za co, a ja regularnie próbuję oferować DLACZEGO za moimi odpowiedziami, aby pomóc innym uczyć się DLACZEGO i zastosować takie rozumowanie w swoich przyszłych pytaniach, które mogą się pojawić. Możesz przejrzeć historię pytań każdego użytkownika, klikając na nie i przeszukując ich tagi (np. [Mysql]) lub cokolwiek innego ... może inne już udzielone odpowiedzi pomogą ci rozwiązać, zanim będziesz musiał zapytać - nie, że prośba jest zawsze zła rzecz. – DRapp

+1

+1 DRapp .. @RossWilson, Kiedy zakresy są zaangażowane powinieneś zawsze najpierw indeksować równości, to pozwala MySQL na użycie większej ilości części z indeksu (co czyni indeks bardziej selektywnym sprawdzeniem key_len w wyjaśnieniu za pomocą tego zapytania może to być większy numer teraz). skanowanie zakresu z> = może używać tylko lewej kolumny z prefiksem, aby odfiltrować nie pasujące rekordy. –