Les sous-requêtes avec EXISTE vs EN - MySQL
Ci-dessous deux requêtes sont des sous-requêtes. Les deux sont le même et les deux fonctionne très bien pour moi. Mais le problème, c'est la Méthode 1 de la requête prend environ 10 secondes pour exécuter tandis que la Méthode 2 de la requête prend moins de 1 sec.
J'ai été en mesure de convertir la méthode 1 de la requête à la méthode 2, mais je ne comprends pas ce qui se passe dans la requête. J'essaie de comprendre moi-même. J'aimerais vraiment savoir quelle est la différence entre ci-dessous deux requêtes et comment le gain de performance se produisent ? quelle est la logique derrière cela ?
Je suis nouveau sur ce advance techniques. J'espère que quelqu'un va m'aider ici. Étant donné que j'ai lu le docs qui ne me donne pas la moindre idée.
Méthode 1 :
SELECT
*
FROM
tracker
WHERE
reservation_id IN (
SELECT
reservation_id
FROM
tracker
GROUP BY
reservation_id
HAVING
(
method = 1
AND type = 0
AND Count(*) > 1
)
OR (
method = 1
AND type = 1
AND Count(*) > 1
)
OR (
method = 2
AND type = 2
AND Count(*) > 0
)
OR (
method = 3
AND type = 0
AND Count(*) > 0
)
OR (
method = 3
AND type = 1
AND Count(*) > 1
)
OR (
method = 3
AND type = 3
AND Count(*) > 0
)
)
Méthode 2 :
SELECT
*
FROM
`tracker` t
WHERE
EXISTS (
SELECT
reservation_id
FROM
`tracker` t3
WHERE
t3.reservation_id = t.reservation_id
GROUP BY
reservation_id
HAVING
(
METHOD = 1
AND TYPE = 0
AND COUNT(*) > 1
)
OR
(
METHOD = 1
AND TYPE = 1
AND COUNT(*) > 1
)
OR
(
METHOD = 2
AND TYPE = 2
AND COUNT(*) > 0
)
OR
(
METHOD = 3
AND TYPE = 0
AND COUNT(*) > 0
)
OR
(
METHOD = 3
AND TYPE = 1
AND COUNT(*) > 1
)
OR
(
METHOD = 3
AND TYPE = 3
AND COUNT(*) > 0
)
)
Vous devez vous connecter pour publier un commentaire.
Un
Expliquer le Plan d'
aurait montré exactement pourquoi vous devriez utiliserExists
. Habituellement, la question seExists vs Count(*)
.Exists
est plus rapide. Pourquoi?À l'égard des défis présents NULLE: lorsque sous-requête retourne
Null
, DANS l'ensemble de la requête devientNull
. Si vous avez besoin de charger. Mais à l'aide deExist
, c'est simplement unfalse
. Beaucoup plus facile de faire face. SimplementIN
ne peut pas comparer n'importe quoi avecNull
maisExists
peut.par exemple
Exists (Select * from yourtable where bla = 'blabla');
vous obtenez vrai/faux le moment un seul coup est trouvé/appariés.Dans ce cas
IN
sorte de la position de laCount(*)
pour sélectionner TOUS correspondance des lignes en fonction de laWHERE
parce que c'est la comparaison de toutes les valeurs.Mais n'oublie pas que ce soit:
EXISTS
exécute à grande vitesse contreIN
: lorsque la sous-requête des résultats est très importante.IN
prend de l'avance deEXISTS
: lorsque la sous-requête des résultats est très faible.De référence pour plus de détails:
La méthode 2 est rapide car c'est à l'aide de
EXISTS
de l'opérateur, où jeMySQL
ne charge pas de résultats.Comme mentionné dans votre docs lien, qu'il omet ce qui est là dans
SELECT
clause. Il vérifie uniquement la première valeur qui correspond aux critères, une fois trouvé, il définit la conditionTRUE
et se déplace pour un traitement ultérieur.De l'autre côté de la Méthode 1 a
IN
opérateur qui charge toutes les valeurs possibles et la compare. Condition deTRUE
uniquement lorsque l'exacte correspondance est trouvée, ce qui est fastidieux processus.Donc votre méthode 2 est rapide.
Espère que ça aide...
La EXISTE opérateur est un opérateur Booléen qui renvoie vrai ou faux. Le EXISTE opérateur est souvent utilisé dans un sous-requête pour tester un “existent l'état”.
Si la sous-requête renvoie toutes les lignes, la EXISTE opérateur renvoie true, sinon, elle retourne false.
En outre, la EXISTE opérateur met fin à la poursuite du traitement immédiatement une fois qu'il trouve une ligne correspondante. En raison de cette caractéristique, vous pouvez utiliser le EXISTE opérateur pour améliorer les performances de la requête dans certains cas.
La PAS opérateur annule la EXISTE de l'opérateur. En d'autres termes, la n'EXISTE PAS retourne vrai si la sous-requête ne renvoie aucune ligne, sinon elle retourne false.
Vous pouvez utiliser SELECT *, SÉLECTIONNER la colonne, SÉLECTIONNEZ a_constant, ou quoi que ce soit dans la sous-requête. Les résultats sont les mêmes parce que MySQL ignore la select_list qui apparaît dans la SÉLECTIONNEZ clause.
La raison en est que la EXISTE opérateur des travaux basés sur le “au moins trouvé” principe. Elle renvoie true et arrête le balayage de la table, une fois au moins une ligne correspondante trouvé.
Sur les autres mains, lorsque le DANS opérateur est combiné avec une sous-requête, MySQL doit traiter la sous-requête en premier et ensuite utilise le résultat de la sous-requête pour traiter la totalité de la requête.
La règle générale est que si la sous-requête contient un grand volume de données, le EXISTE opérateur fournit une meilleure performance.
Toutefois, la requête qui utilise la DANS opérateur effectuer plus rapidement si le jeu de résultats retourné par la sous-requête est très faible.
Pour le détail des explications et des exemples: MySQL EXISTE - mysqltutorial.org
La deuxième Méthode est plus rapide parce que vous avez obtenu ce que là "OÙ t3.reservation_id = t.reservation_id". Dans le premier cas, votre sous-requête doit faire un balayage complet de la table de vérification de l'information. Cependant au 2o de la Méthode de la sous-requête ne sait exactement ce qu'elle cherche et une fois qu'il est trouvé est vérifiée la condition d'avoir ensuite.
La Documentation Officielle.Sous-requête d'Optimisation avec Existe