Jeśli wartości dla kolumny B nie są dostępne na stronach indeksu, wówczas MySQL będzie musiał uzyskać dostęp do stron w tabeli podstawowej. Także tam nie ma predykatu, który filtruje, które wiersze są brane pod uwagę, a to oznacza, że MySQL widzi, że WSZYSTKIE wiersze muszą zostać zwrócone. To może wyjaśnić, dlaczego indeks nie jest używany.
Należy również zauważyć, że operacje LIMIT
są przetwarzane na końcu instrukcji, jako prawie ostatni krok w planie wykonania, z pewnymi wyjątkami.
8.2.1.3. Optimizing LIMIT Queries http://dev.mysql.com/doc/refman/5.5/en/limit-optimization.html
Podejrzewam, że zapytanie mogłoby skorzystać z indeksu przewodnim, na przykład „ON hugetable (A,B)
”, aby uniknąć operacji sortowania.
W przypadku braku indeksu obejmującego można spróbować przepisać zapytanie w taki sposób, aby sprawdzić, czy skorzysta z indeksu w kolumnie A, i uniknąć operacji sortowania w milionach wierszy (aby uzyskać pierwsze 510 000 wierszy zwróconych w kolejności):
SELECT i.B
FROM (SELECT j.A
FROM hugeTable j
ORDER
BY j.A
LIMIT 10000 OFFSET 500000
) k
JOIN hugetable i
ON i.A = k.A
ORDER
BY k.A
proponuję zrobić EXPLAIN
tylko na zapytania widoku inline (alias jako K), i zobaczyć, czy to widać „Using index
”.
Zewnętrzne zapytanie prawdopodobnie nadal będzie miało operację "Using filesort
", ale co najmniej będzie to dotyczyło tylko 10 000 wierszy.
(UWAGA: Możesz spróbować "ORDER BY i.A
" zamiast "k.A
" na zewnętrznej kwerendy, i sprawdzić, czy to robi różnicę.)
DODATEK
Nie odpowiadając konkretnie na twoje pytanie, ale pod względem wydajności tego zapytania, jeśli jest to "przekierowanie" przez zestaw wierszy, inną opcją do rozważenia, aby przejść do "następnej" strony jest użycie wartości "A
" z ostatni wiersz pobrany w poprzednim zapytaniu jako "punkt początkowy" dla t następny wiersz.
Oryginalne zapytanie wygląda na to, że zaczyna "strona 51" (10 000 wierszy na stronę, strona 51 to wiersze od 510,001 do 520 000).
Jeśli miałbyś również zwrócić wartość "A" i zachować ją dla ostatniego rzędu.Aby dostać się „obok” stronę, zapytanie może faktycznie być:
SELECT i.B, k.A
FROM (SELECT j.A
FROM hugeTable j
WHERE j.A > $value_of_A_from_row_520000
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LIMIT 10000
) k
JOIN hugetable i
ON i.A = k.A
ORDER
BY k.A
Jeśli również przechowywane wartości dla A z „pierwszego rzędu”, które można użyć do tworzenia kopii zapasowych stronę. To naprawdę działa tylko w przypadku przekazania jednej strony lub cofnięcia o jedną stronę. Przeskakując na inną stronę, musiałbyś użyć oryginalnej formy zapytania, licząc wiersze.