Je me demande s'il y a une différence en termes de performances entre les éléments suivants
SELECT ... FROM ... WHERE someFIELD IN(1,2,3,4)
SELECT ... FROM ... WHERE someFIELD between 0 AND 5
SELECT ... FROM ... WHERE someFIELD = 1 OR someFIELD = 2 OR someFIELD = 3 ...
ou MySQL optimisera-t-il le SQL de la même manière que les compilateurs optimiseront le code?
EDIT: Changé le AND
's en OR
' s pour la raison indiquée dans les commentaires.
mysql
sql
performance
optimization
Scott
la source
la source
s I could say that it can also be converted to UNION
ce qui est recommandé pour remplacer OR pour optimiser la requête.Réponses:
J'avais besoin de le savoir avec certitude, alors j'ai évalué les deux méthodes. J'ai toujours trouvé
IN
beaucoup plus rapide que l'utilisationOR
.Ne croyez pas les gens qui donnent leur "opinion", la science est une question de tests et de preuves.
J'ai exécuté une boucle de 1000x les requêtes équivalentes (par souci de cohérence, j'ai utilisé
sql_no_cache
):IN
: 2.34969592094sOR
: 5.83781504631sMise à jour:
(je n'ai pas le code source du test d'origine, comme il y a 6 ans, bien qu'il renvoie un résultat dans la même plage que ce test)
Dans la demande d'un exemple de code pour tester cela, voici le cas d'utilisation le plus simple possible. En utilisant Eloquent pour la simplicité de la syntaxe, l'équivalent SQL brut exécute la même chose.
la source
IN
déclaration était environ 30% plus rapide qu'un fichierOR
.Do not believe people who give their "opinion"
Vous avez 100% raison, Stack Overflow en est malheureusement pleinReturns 1 if expr is equal to any of the values in the IN list, else returns 0. If all values are constants, they are evaluated according to the type of expr and sorted. The search for the item then is done using a binary search. This means
IN is very quick if the IN value list consists entirely of constants
. Otherwise, type conversion takes place according to the rules described at Type Conversion, but applied to all the arguments.
IN
J'ai également fait un test pour les futurs Googleurs. Le nombre total de résultats renvoyés est de 7264 sur 10000
Cette requête a pris
0.1239
quelques secondesCette requête a pris
0.0433
quelques secondesIN
est 3 fois plus rapide queOR
la source
OR
: mieux vaut utiliser l'expression la plus compacte possible.La réponse acceptée n'explique pas la raison.
Ci-dessous sont cités de High Performance MySQL, 3e édition.
la source
Je pense que le BETWEEN sera plus rapide puisqu'il devrait être converti en:
Je crois comprendre qu'un IN sera converti de toute façon en un tas d'instructions OR. La valeur de IN est la facilité d'utilisation. (Vous évitez d'avoir à taper chaque nom de colonne plusieurs fois et cela facilite également l'utilisation avec la logique existante - vous n'avez pas à vous soucier de la priorité AND / OR car IN est une instruction. Avec un tas d'instructions OR, vous avez pour vous assurer de les entourer de parenthèses pour vous assurer qu'elles sont évaluées comme une seule condition.)
La seule vraie réponse à votre question est PROFILER VOS QUESTIONS . Vous saurez alors ce qui fonctionne le mieux dans votre situation particulière.
la source
Cela dépend de ce que vous faites; quelle est la largeur de la plage, quel est le type de données (je sais que votre exemple utilise un type de données numérique, mais votre question peut également s'appliquer à de nombreux types de données différents).
Il s'agit d'une instance dans laquelle vous souhaitez écrire la requête dans les deux sens; faites-le fonctionner, puis utilisez EXPLAIN pour déterminer les différences d'exécution.
Je suis sûr qu'il y a une réponse concrète à cela, mais c'est ainsi que je pourrais, en pratique, trouver la réponse à ma question donnée.
Cela peut être utile: http://forge.mysql.com/wiki/Top10SQLPerformanceTips
Cordialement,
Frank
la source
Je pense qu'une explication à l'observation de sunseeker est que MySQL trie en fait les valeurs dans l'instruction IN si elles sont toutes des valeurs statiques et utilisent la recherche binaire, ce qui est plus efficace que l'alternative OR ordinaire. Je ne me souviens plus où j'ai lu cela, mais le résultat de Sunseeker semble en être une preuve.
la source
Juste au moment où vous pensiez que c'était sûr ...
Quelle est votre valeur
eq_range_index_dive_limit
? En particulier, avez-vous plus ou moins d'articles dans l'IN
article?Cela n'inclura pas de benchmark, mais examinera un peu le fonctionnement interne. Utilisons un outil pour voir ce qui se passe - Optimizer Trace.
La requête:
SELECT * FROM canada WHERE id ...
Avec une valeur
OR
de 3 , une partie de la trace ressemble à:...
...
Notez comment ICP est donné
ORs
. Cela implique que celaOR
n'est pas transformé enIN
, et InnoDB effectuera un tas de=
tests via ICP. (Je ne pense pas que cela vaille la peine de considérer MyISAM.)(Ceci est le 5.6.22-71.0-log de Percona;
id
est un index secondaire.)Maintenant pour IN () avec quelques valeurs
eq_range_index_dive_limit
= 10; il y a 8 valeurs....
...
Notez que le
IN
ne semble pas être transformé enOR
.Remarque: notez que les valeurs constantes ont été triées . Cela peut être bénéfique de deux manières:
Enfin, IN () avec beaucoup de valeurs
...
...
Note latérale: J'en avais besoin en raison de l'encombrement de la trace:
la source
OU sera le plus lent. Que IN ou BETWEEN soit plus rapide dépendra de vos données, mais je m'attendrais à ce que BETWEEN soit plus rapide normalement car il peut simplement prendre une plage à partir d'un index (en supposant que someField est indexé).
la source
Vous trouverez ci-dessous les détails de 6 requêtes utilisant MySQL 5.6 @SQLFiddle
En résumé, les 6 requêtes couvrent des colonnes indexées indépendamment et 2 requêtes ont été utilisées par type de données. Toutes les requêtes ont abouti à l'utilisation d'un index indépendamment de IN () ou ORs utilisés.
Je voulais vraiment juste démystifier les déclarations faites que OU signifie qu'aucun index ne peut être utilisé. Ce n'est pas vrai. Les index peuvent être utilisés dans les requêtes en utilisant OR comme les 6 requêtes dans les exemples suivants s'affichent.
De plus, il me semble que beaucoup ont ignoré le fait que IN () est un raccourci syntaxique pour un ensemble de OU. À petite échelle, les différences de performances entre l'utilisation de IN () -v- OR sont extrêmement (en fait) marginales.
Alors qu'à plus grande échelle, IN () est certainement plus pratique, mais cela équivaut toujours à un ensemble de conditions OU logiquement. Changement de circonstance pour chaque requête, il est donc toujours préférable de tester votre requête sur vos tables.
Résumé des 6 plans d'explication, tous "Utilisation de la condition d'index" (défilement vers la droite)
Violon SQL
Configuration du schéma MySQL 5.6 :
.
Requête 1 :
Résultats :
Requête 2 :
Résultats :
Requête 3 :
Résultats :
Requête 4 :
Résultats :
Requête 5 :
Résultats :
Requête 6 :
Résultats :
la source
Je parie que ce sont les mêmes, vous pouvez exécuter un test en procédant comme suit:
bouclez 500 fois le "in (1,2,3,4)" et voyez combien de temps cela prend. boucle sur la version "= 1 ou = 2 ou = 3 ..." 500 fois et voir combien de temps il s'exécute.
vous pouvez également essayer une méthode de jointure, si someField est un index et que votre table est grande, cela pourrait être plus rapide ...
J'ai essayé la méthode de jointure ci-dessus sur mon serveur SQL et elle est presque la même que dans (1, 2, 3, 4), et elles résultent toutes deux en une recherche d'index groupé. Je ne sais pas comment MySQL va les gérer.
la source
2018 : IN (...) est plus rapide. Mais > = && <= est encore plus rapide que IN .
Voici ma référence .
la source
D'après ce que je comprends de la façon dont le compilateur optimise ces types de requêtes, l'utilisation de la clause IN est plus efficace que plusieurs clauses OR. Si vous avez des valeurs où la clause BETWEEN peut être utilisée, c'est encore plus efficace.
la source
Je sais que, tant que vous avez un index sur Field, le BETWEEN l'utilisera pour trouver rapidement une extrémité, puis traversera vers l'autre. C'est le plus efficace.
Chaque EXPLAIN que j'ai vu montre que "IN (...)" et "... OR ..." sont interchangeables et tout aussi (in) efficaces. Ce à quoi vous vous attendez, car l'optimiseur n'a aucun moyen de savoir s'ils comprennent ou non un intervalle. Cela équivaut également à UNION ALL SELECT sur les valeurs individuelles.
la source
Comme expliqué par d'autres, IN est mieux choisi que OR en ce qui concerne les performances des requêtes.
Les requêtes avec une condition OR peuvent prendre plus de temps d'exécution dans les cas ci-dessous.
la source