MySQL Query molto lento quando si cambia uno dove campo nonostante nessun / chiave di indice
Domanda
Questo è piuttosto un problema di confusione per me. Ho un database pieno di statistiche di baseball. L'esecuzione di questo query:
SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN games ON games.gameName = hits.gameName
WHERE games.type = 'R'
LIMIT 50
Returns:
/* 0 rows affected, 50 rows found. Duration for 1 query: 0.218 sec. */
Ma l'esecuzione di questa query:
SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN games ON games.gameName = hits.gameName
WHERE games.leagueLevel = 'mlb'
LIMIT 50
si blocca per un lungo periodo di tempo. L'indice sul tavolo da gioco è solo games.gameName e nient'altro.
Selezionare il tipo di DISTINTO DA giochi dà 8 righe di un solo carattere (VARCHAR 1) tra cui uno NULL.
SELEZIONARE leagueLevel DISTINTO DA giochi dà 6 file di tre caratteri (VARCHAR 5) tra cui uno NULL.
Non ho idea del motivo per cui la seconda query sarebbe straordinariamente lento, mentre il primo viene eseguito bene.
Grazie per il vostro aiuto.
Soluzione
PUNTO DI VISTA # 1: molti devono dare un'occhiata a popolazione valore colonna
SELECT COUNT(1) rowount,type FROM games GROUP BY type WITH ROLLUP;
SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;
Dalla tua domanda, mi sembra di capire due cose:
- Il numero di righe nei giochi con type = 'R' deve essere un numero basso rispetto al numero di righe della tabella giochi.
- Il numero di righe nei giochi con leaguelevel = 'mlb' deve essere un numero elevato (superiore al 5% della tabella) rispetto al numero di righe della tabella giochi. (5% è un numero regola empirica agli occhi di ottimizzatori di query)
PUNTO DI VISTA # 2: Potrebbe essere necessario refactoring questa query
Si noti che query eseguire la WHERE parte, dopo tutti i join sono completi. Se la parte in cui potrebbe essere eseguita in precedenza che potrebbe contribuire a ridurre il tempo. Prova riorganizzare la query in questo modo:
SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN (SELECT * FROM games WHERE leagueLevel = 'mlb') games
ON games.gameName = hits.gameName
LIMIT 50;
PUNTO DI VISTA # 3: Recupera solo le colonne si ha realmente bisogno
Vedo che hai SELECT * e si dispone di quattro tavoli (hits, stadi, giocatori, giochi). Avrete un sacco di dati duplicati per trascinare nella query, in particolare quando si trascina la colonna GameName da tutti e quattro tabelle.
Si dovrebbe riorganizzare la query di portare una sola colonna GameName:
SELECT hits.gameName,hits.*,players.*,staduims.*,games.* FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN (SELECT * FROM games WHERE leagueLevel = 'mlb') games
ON games.gameName = hits.gameName
LIMIT 50;
Inoltre, se non avete bisogno di tutte le colonne dalle tabelle colpi, quindi includere solo la colonna si sa si accede. Lo stesso vale per i giocatori, stadi, e giochi.
In altre parole, a titolo di esempio, se avete solo bisogno il playername dalla tabella giocatore, quindi non è necessario giocatore. * Nella SELECT. Avrete bisogno solo player.playerName.
PUNTO DI VISTA # 4: potrebbe essere necessario per indicizzare la colonna leagueLevel
Sarà necessario effettuare le seguenti operazioni per rendere l'indice necessarie:
ALTER TABLE games ADD INDEX (leagueLevel);
Prima di fare ciò, eseguire questo
SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;
Qualsiasi valore per leagueLevel cui valore è maggiore di 5% della tabella causerà il MySQL Query Optimizer non utilizzare l'indice.
Altri suggerimenti
Non ho idea del motivo per cui la seconda query sarebbe straordinariamente lento mentre il primo viene eseguito bene.
Non siete soli - è molto comune avere per approfondire il perché e il percome specifiche di esecuzione della query
. È necessario imparare a utilizzare gli strumenti che avete a disposizione, a partire da explain
e explain extended
. Fateci sapere come si ottiene ...
Sei solo la fortuna di avere i primi ritorni di query veloce. Sono d'accordo con @Jack Douglas, uso spiegare, aggiungere gli indici necessari, e ripetere fino a quando entrambe le query migliorato molto meglio.