MySQL Query molto lento quando si cambia uno dove campo nonostante nessun / chiave di indice

dba.stackexchange https://dba.stackexchange.com/questions/3780

  •  16-10-2019
  •  | 
  •  

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.

È stato utile?

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:

  1. Il numero di righe nei giochi con type = 'R' deve essere un numero basso rispetto al numero di righe della tabella giochi.
  2. 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top