MySQL requête très lent lors de la modification d'un champ Où malgré l'absence d'index / clé

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

  •  16-10-2019
  •  | 
  •  

Question

Ceci est une question tout à fait déroutant pour moi. J'ai une base de données complète des statistiques de base-ball. L'exécution de cette requête:

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

Renvoie:

/* 0 rows affected, 50 rows found. Duration for 1 query: 0.218 sec. */

Mais l'exécution de cette requête:

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

pour une longue Hangs temps. L'index sur la table de jeux est seulement games.gameName et rien d'autre.

Sélectionner le type de jeux donne DISTINCT 8 lignes d'un seul caractère (VARCHAR 1) dont un NULL.

SELECT leagueLevel des jeux donne DISTINCT 6 rangées de trois caractères (VARCHAR 5) dont un NULL.

Je ne sais pas pourquoi la deuxième requête serait extraordinairement lente alors que le premier fonctionne très bien.

Merci pour votre aide.

Était-ce utile?

La solution

TÉMOIGNAGE # 1: Vous beaucoup besoin de jeter un oeil à la population de valeur de la colonne

SELECT COUNT(1) rowount,type FROM games GROUP BY type WITH ROLLUP;
SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;

A partir de votre question, je crois deux choses:

  1. Le nombre de lignes dans les jeux de type = « R » doit être un faible nombre par rapport au nombre de lignes dans la table de jeux.
  2. Le nombre de lignes dans les jeux avec leaguelevel = « mlb » doit être un nombre élevé (supérieur à 5% de la table) par rapport au nombre de lignes dans la table de jeux. (5% est un nombre de règles de pouce dans les yeux de Optimiseurs de requêtes)

TÉMOIGNAGE # 2: Vous devrez peut-être factoriser cette requête

Notez que la requête effectuera la partie WHERE après tout JOIN sont complètes. Si la partie WHERE pourrait être réalisée plus tôt qui pourrait aider à réduire le temps. Essayez de réorganiser la requête comme ceci:

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;

POINT DE VUE # 3: récupérer uniquement les colonnes que vous avez vraiment besoin

Je vois que vous avez SELECT * et vous avez quatre tables (hits, stades, joueurs, jeux). Vous aurez beaucoup de données en double à glisser dans la requête, en particulier lorsque vous faites glisser la colonne gamename de quatre tables.

Vous devriez réorganiser la requête pour faire une seule colonne 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;

En outre, si vous n'avez pas besoin chaque colonne des tables hits, alors ne comprennent que la colonne que vous savez que vous aurez accès. La même chose vaut pour les joueurs, les stades et les jeux.

En d'autres termes, à titre d'exemple, si vous avez seulement besoin playername de la table des joueurs, vous ne pas besoin de joueur. * Dans le SELECT. Vous avez juste besoin player.playerName.

TÉMOIGNAGE # 4: Vous devrez peut-indexer la colonne leagueLevel

Vous devez faire ce qui suit pour faire l'index nécessaire:

ALTER TABLE games ADD INDEX (leagueLevel);

Avant de le faire, exécutez

SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;

Toute valeur pour leagueLevel dont le nombre est supérieur à 5% de la table provoque l'optimiseur de requêtes MySQL de ne pas utiliser l'index.

Autres conseils

  

Je ne sais pas pourquoi la deuxième requête serait extraordinairement lente   tandis que le premier fonctionne très bien.

Vous n'êtes pas seul - il est très fréquent d'avoir à plonger plus profondément dans les spécifiques et de pourquoi les aboutissants de l'exécution des requêtes

.

Vous devez apprendre à utiliser les outils dont vous disposez, en commençant par explain extended . Faites-nous savoir comment vous allez ...

Vous êtes juste assez chanceux pour obtenir les premiers retours de requête rapide. Je suis d'accord avec @Jack Douglas, l'utilisation expliquer, ajouter les index nécessaires, et répéter jusqu'à ce que les requêtes ont amélioré beaucoup mieux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top