L'ordre des champs dans une clause where influer sur les performances de MySQL?
J'ai deux champs indexés dans une table - type
et userid
(des indices individuels, pas un composite).
type
s valeurs de champ sont très limitées (disons que c'est seulement 0 ou 1), de sorte que 50% des enregistrements de la table ont le même type
. userid
valeurs, d'autre part, venir à partir d'un ensemble beaucoup plus volumineux, de sorte que le montant des enregistrements avec le même userid
est petit.
Aucune de ces requêtes s'exécutent plus rapidement que les autres:
select * from table where type=1 and userid=5
select * from table where userid=5 and type=1
Aussi si les deux champs n'ont pas été indexés, serait-il modifier le comportement?
- Double Possible de N'afin de où les clauses de la matière dans SQL
Vous devez vous connecter pour publier un commentaire.
SQL a été conçu pour être un langage déclaratif, et non une procédure. Donc, l'optimiseur de requête doit pas prendre en considération l'ordre de la clause where de prédicats dans la détermination de la façon de les appliquer.
Je vais probablement sa réputation sur-simplifier la suite de la discussion d'une requête SQL optimizer. J'ai écrit un ans, le long de ces lignes (c'est des tonnes de plaisir!). Si vous voulez vraiment creuser dans moderne d'optimisation de requête, voir Dan le Remorquage du SQL Tuning, d'O ' Reilly.
Dans une simple requête SQL optimizer, l'instruction SQL obtient d'abord compilé en un arbre de de l'algèbre relationnelle opérations. Ces opérations prennent chacun une ou plusieurs tables d'entrée et de produire une autre table en sortie. Analyse est un balayage séquentiel qui lit une table de la base de données. Sorte produit un tableau trié. Sélectionnez produit un tableau dont les lignes sont sélectionnées à partir d'une autre table selon certaines condition de sélection. Projet produit un tableau avec seulement certaines colonnes d'une autre table. De la croix-Produit prend deux tables et produit une sortie de table composé de tous les moyens imaginables pour l'appariement de leurs lignes.
Point de prêter à confusion, le SQL clause SELECT est compilé dans une algèbre relationnelle Projet, tandis que la clause where se transforme en une algèbre relationnelle Sélectionnez. La clause from se transforme en une ou plusieurs Rejoint, chaque prise de deux tables et de produire une table. Il y a d'autres opérations de l'algèbre relationnelle impliquant l'ensemble de l'union, intersection, différence, et de l'adhésion, mais gardons ça simple.
Cet arbre a vraiment besoin d'être optimisé. Par exemple, si vous avez:
avec 5 000 employés dans 500 départements, l'exécution d'un unoptimized arbre aveuglément produire toutes les combinaisons possibles d'un Employé et un Département (un de la Croix-Produit) et puis Sélectionnez exactement la combinaison qui a été nécessaire. Le Analyse de l'Employé va produire de plus de 5 000 enregistrement de la table, le Analyse du Ministère publiera un 500 enregistrement de la table, le de la Croix-Produit de ces deux tableaux de produire un 2,500,000 enregistrement de la table, et le Sélectionnez sur E. l'id de la prendre que de 2 500 000 d'enregistrement de la table et jetez tous, sauf un, l'enregistrement qui a été voulu.
[Réel de requête processeurs va essayer de ne pas se matérialiser tous ces tableaux intermédiaires en mémoire du cours.]
Si l'optimiseur de requête promenades de l'arbre et s'applique diverses optimisations. L'un est de casser chaque Sélectionnez dans une chaîne de Sélectionne, un pour chaque original Sélectionnez's haut niveau, les uns et par-ed ensemble. (Ce qui est appelé "conjonctif " normale".) Alors l'individu plus petit Sélectionne sont déplacés dans l'arbre et ont fusionné avec d'autres opérations de l'algèbre relationnelle pour former plus efficaces.
Dans l'exemple ci-dessus, l'optimiseur de première pousse le Sélectionnez sur E. id = 123456 vers le bas ci-dessous le cher de la Croix-Produit opération. Cela signifie que le de la Croix-Produit ne produit que 500 lignes (une pour chaque combinaison de l'employé et d'un ministère). Puis le haut niveau Sélectionnez pour E. dept_id = D. dept_id filtre les 499 indésirables lignes. C'est pas mal.
Si il y a un indice sur l'id de l'Employé, puis l'optimiseur peut combiner les Analyse de l'Employé avec l' Sélectionnez sur E. id = 123456 pour former un index de Recherche. Cela signifie qu'un seul Employé ligne est lu en mémoire à partir du disque, au lieu de 5000. Les choses s'améliorent.
La dernière majeur de l'optimisation est de prendre le Sélectionnez sur E. dept_id = D. dept_id et de le combiner avec la de la Croix-Produit. Cela en fait une algèbre relationnelle équi-jointure opération. Ce n'est pas faire beaucoup par lui-même. Mais si il y a un indice sur le Département.dept_id, le plus faible niveau séquentiel Analyse Ministère de l'alimentation de la équi-jointure peut être transformé en un très rapide de l'indice de de Recherche de notre un employé du Département de l'enregistrement.
Moindre optimisations impliquer poussant Projet opérations vers le bas. Si le haut niveau de votre requête a juste besoin de E. nom et D. nom, et les conditions de nécessité E. id, E. dept_id, et D. dept_id, puis le Analyse opérations n'ont pas pour construire des tableaux intermédiaires avec toutes les autres colonnes, de gagner de l'espace lors de l'exécution de la requête. Nous avons tourné un horriblement lent requête dans les deux index de recherches et pas grand chose d'autre.
Arriver de plus en plus vers la question d'origine, disons que vous avez:
La unoptimized de l'algèbre relationnelle de l'arbre, lorsqu'il est exécuté, Numériser dans la 5 000 employés et de produire, par exemple, la 126 dans le Delaware qui sont âgés de plus de 21. L'optimiseur de requête a aussi une idée des valeurs dans la base de données. Il pourrait savoir que l'E. de l'état de la colonne a, le 14 prévoit que la société possède des bureaux en, et quelque chose à propos de l'E. la répartition par âge. Alors d'abord il voit si le champ est indexé. Si E. état, il est préférable de n'utiliser que de l'indice de prendre le petit nombre d'employés, le processeur de requêtes suspects sont dans le Delaware basé sur son dernier calculée de la statistique. Si seulement E. est de l'âge, le processeur de requêtes susceptibles décide que c'est pas la peine, puisque 96% de tous les employés sont de 22 et plus. Donc, si E. état est indexé, notre processeur de requêtes rompt le Sélectionnez et fusionne les E. état = 'Delaware" avec le Analyse pour le transformer en beaucoup plus efficace Index Scan.
Disons que dans cet exemple qu'il n'y a pas d'index sur E. état et E. l'âge. Le combiné Sélectionnez opération a lieu après la séquence de balayage "Scan" de l'Employé. Cela fait-il une différence de condition dans le Sélectionnez est fait en premier? Probablement pas une bonne affaire. Le processeur de requêtes est préférable de les laisser dans l'ordre d'origine dans l'instruction SQL, ou il peut être un peu plus sophistiqué et regarder à la dépense prévue. D'après les statistiques, il serait à nouveau trouver que les E. état = 'Delaware l'état devrait être plus très sélective, de sorte qu'il aurait pour effet d'inverser les conditions et le faire, de sorte qu'il y a seulement 126 E. age > 21 les comparaisons au lieu de 5000. Ou il pourrait réaliser que la chaîne de l'égalité des comparaisons sont beaucoup plus chers que les entier et compare quitter l'ordre tout seul.
En tout cas, tout cela est très complexe et votre condition syntaxique est très peu probable de faire une différence. Je ne serais pas s'inquiéter à ce sujet, sauf si vous avez un réel problème de performances et de votre fournisseur de base de données utilise la condition de l'ordre comme un indice.
La plupart des optimiseurs de requêtes utilisation l'ordre dans lequel les conditions apparaissent comme un indice. Si tout le reste est égal, ils vont suivre cet ordre.
Cependant, beaucoup de choses peuvent ignorer que:
varchar(max)
vsint
)Donc (et cela est vrai pour toutes les SQL optimisation questions), sauf si vous observez un problème de performances, il est préférable d'optimiser la clarté, non pas pour les (supposées) de la performance.
Il ne devrait pas dans votre petit exemple. L'optimiseur de requête devrait faire la bonne chose. Vous pouvez le vérifier grâce à l'ajout de
explain
à l'avant de la requête. MySQL va vous dire comment c'est rejoindre des choses ensemble et combien de lignes il a besoin de recherche dans le but de faire la jointure. Par exemple:explain select * from table where type=1 and userid=5
Si elles n'ont pas été indexés, il serait probablement un changement de comportement.