Se i valori per la colonna B non sono disponibili nelle pagine indice, MySQL dovrà accedere alle pagine nella tabella sottostante. Inoltre non esiste un predicato che filtri quali righe siano prese in considerazione e ciò significa che MySQL sta vedendo che TUTTE le righe devono essere restituite. Questo potrebbe spiegare perché l'indice non viene utilizzato.
Si noti inoltre che le operazioni LIMIT
vengono elaborate alla fine dell'istruzione, come quasi l'ultimo passaggio nel piano di esecuzione, con alcune eccezioni.
8.2.1.3. Optimizing LIMIT Queries http://dev.mysql.com/doc/refman/5.5/en/limit-optimization.html
ho il sospetto che la query potrebbe fare uso di un indice di copertura, ad esempio "ON hugetable (A,B)
", al fine di evitare l'operazione di ordinamento.
In assenza di un indice di copertura, è possibile provare a riscrivere la query in questo modo, per vedere se questo farà uso dell'indice sulla colonna A ed evitare un'operazione di ordinamento su milioni di righe (per ottenere le prime 510.000 righe restituite in ordine):
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
ti suggerisco di fare un EXPLAIN
solo su query vista in linea (alias come k), e vedere se mostra "Using index
."
È probabile che la query esterna abbia ancora l'operazione "Using filesort
", ma almeno sarà su solo 10.000 righe.
(NOTA: Si consiglia di provare un "ORDER BY i.A
" al posto di "k.A
" sulla query esterna, e vedere se questo fa la differenza.)
ADDENDUM
Non indirizzando in modo specifico la domanda, ma in termini di prestazioni di tale query, se si tratta di "sfogliare" un insieme di righe, un'altra opzione da considerare, per arrivare alla pagina "successiva" è utilizzare il valore di "A
" da l'ultima riga recuperata nella query precedente come "punto di partenza" per t la prossima fila.
La query originale sembra ricevere "pagina 51" (10.000 righe per pagina, la pagina 51 sarebbe una riga da 510.001 a 520.000).
Se si dovesse anche restituire il valore di 'A' e mantenerlo per l'ultima riga.Per ottenere la pagina "successiva", la query potrebbe effettivamente essere:
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
Se anche hai tenuto il valore di A dalla riga "prima", è possibile utilizzare che per il backup di una pagina. Ciò funzionerebbe davvero solo per inoltrare una pagina o tornare indietro di una pagina. Saltare su una pagina diversa, dovrebbe utilizzare la forma originale della query, contando le righe.