12
votes

Cette requête de sélection prend 180 secondes pour terminer

mise à jour:

juste pour le mentionner sur un endroit plus visible. Lorsque j'ai changé pour =, le temps d'exécution de la requête est passé de 180 à 0,00008 secondes. Différence de vitesse ridicule. P>


Cette requête SQL prend 180 secondes pour finir! Comment est-ce possible? Y a-t-il un moyen d'optimiser cela pour être plus rapide? P>

SELECT IdLawVersionValidFrom 
FROM question_law_version 
WHERE IdQuestionLawVersion IN 
  (
  SELECT MAX(IdQuestionLawVersion) 
  FROM question_law_version 
  WHERE IdQuestionLaw IN 
    (
    SELECT MIN(IdQuestionLaw) 
    FROM question_law 
    WHERE IdQuestion=236 AND IdQuestionLaw>63
    )
  )


6 commentaires

Toute différence si vous modifiez le dans sur = ?


Ces noms de colonne me font mal au cerveau. Pouvez-vous expliquer ce que la requête est censée faire?


@Martin Smith, il serait surprenant (et éducatif pour moi) si cela fait de la différence.


@Aitay - En effet, c'était une suggestion quelque peu spéculative.


@ Martin Smith qui a effectivement travaillé: o Il est passé de 180 secondes à 0,00008. S'il vous plaît poster cela comme une réponse afin que je puisse l'accepter :)


@Martin Smith - très éducatif à moi - merci (mais toujours étrange, je me demande pourquoi c'est comme ça)


3 Réponses :


12
votes

Voici une bonne explication Pourquoi = est meilleur que dans

MySQL a des problèmes avec les requêtes internes - pas bien en utilisant des index (si du tout).

  1. Assurez-vous que vous avez des index sur tous les champs de la jointure / où / commander, etc.
  2. Obtenez ces valeurs max et min dans une requête séparée (utilisez la procédure stockée pour tout ce qui est de savoir si vous souhaitez ignorer les multiples demandes en tête ou simplement faire une demande avec plusieurs requêtes.

    Quoi qu'il en soit: xxx


1 commentaires

Je serai capable de le tester demain. J'ai la demande dans mon ordinateur de travail et je suis déjà à la maison.



4
votes

Vous pouvez utiliser expliquer code> pour savoir comment est-il possible pour une requête d'exécuter si lentement.

mysql n'aime pas vraiment les sous-éléments imbriqués, donc probablement ce qui se passe probablement sur disque pour obtenir min et max et ne pas réutiliser les résultats. p>

la réécriture comme des jointures l'aiderait probablement. p>

Si vous recherchez une solution rapide, essayez: P>

SET @temp1 =     
  (
  SELECT MIN(IdQuestionLaw) 
  FROM question_law 
  WHERE IdQuestion = 236 AND IdQuestionLaw > 63
  )

SET @temp2 = 
  (
  SELECT MAX(IdQuestionLawVersion) 
  FROM question_law_version 
  WHERE IdQuestionLaw = @temp1
  )

SELECT IdLawVersionValidFrom 
FROM question_law_version 
WHERE IdQuestionLawVersion = @temp2


1 commentaires

Complètement d'accord et a donné +1 à cela. Notez son utilisation de expliquer :)



16
votes

(Postage de mon commentaire comme une réponse comme apparemment cela a fait une différence!)

toute différence si vous modifiez le dans code> à = code>? p> blockQuote>

Si quelqu'un veut enquêter plus loin, je viens de faire un test et j'ai trouvé très facile à reproduire. p>

Créer une table p>

SELECT id 
FROM filler 
WHERE id in  (SELECT MAX(id) FROM filler  WHERE id in   
 ( SELECT MIN(id) 
    FROM filler
    WHERE id between 2000 and 3000
    )
  )


2 commentaires

Je serais curieux pour certains experts de MySQL commenter la différence de performance. Clairement, les sous-sollicités vont retourner 1 rangée uniquement si équivaut est le bon opérateur, mais pourquoi utiliserait une différence de performance aussi importante lorsqu'il ne vérifie que si la valeur est trouvée dans un résultat d'une ligne?


@Wade - La réponse de Mark ici a couvert, je pense Stackoverflow.com/Questtions/3417074/...