Ecco uno scenario che è emerso proprio di recente al lavoro.
Considera tre tabelle, A, B, C.
A ha 3.000 righe; B ha 300.000.000 di righe; e C ha 2.000 righe.
Le chiavi esterne sono definite: B (a_id), B (c_id).
Supponi di avere una query simile a questa:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
Nella mia esperienza, MySQL può scegliere di andare C -> B -> A in questo caso. C è più piccolo di A e B è enorme e sono tutti equijoin.
Il problema è che MySQL non tiene necessariamente conto della dimensione dell'intersezione tra (C.id e B.c_id) vs (A.id e B.a_id). Se l'unione tra B e C restituisce tante righe quante B, allora è una scelta molto scarsa; se iniziare con A avesse filtrato B fino a tante righe quante A, sarebbe stata una scelta molto migliore. straight_join
potrebbe essere usato per forzare questo ordine in questo modo:
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
Ora a
deve essere unito prima b
.
In genere si desidera eseguire i join in un ordine che riduca al minimo il numero di righe nel set risultante. Quindi, iniziare con un tavolino e unire in modo tale che anche l'unione risultante sia piccola, è l'ideale. Le cose vanno a forma di pera se si inizia con un tavolino e lo si unisce a un tavolo più grande e si finisce con le dimensioni del tavolo grande.
Tuttavia dipende dalle statistiche. Se la distribuzione dei dati cambia, il calcolo potrebbe cambiare. Dipende anche dai dettagli di implementazione del meccanismo di join.
I casi peggiori che ho visto per MySQL in cui tutti i straight_join
suggerimenti sull'indice tranne quelli richiesti o aggressivi sono query che si impaginano su molti dati in un rigoroso ordinamento con un leggero filtraggio. MySQL preferisce fortemente utilizzare gli indici per qualsiasi filtro e join rispetto agli ordinamenti; questo ha senso perché la maggior parte delle persone non sta cercando di ordinare l'intero database ma ha piuttosto un sottoinsieme limitato di righe che risponde alla query, e l'ordinamento di un sottoinsieme limitato è molto più veloce del filtrare l'intera tabella, indipendentemente dal fatto che sia ordinato o non. In questo caso, mettendo straight join immediatamente dopo la tabella che aveva la colonna indicizzata, volevo ordinare le cose fisse.
straight_join
.