Je comprends comment ORDER BY
fonctionne la clause et comment FIELD()
fonctionne la fonction. Ce que je veux comprendre, c'est comment les deux travaillent ensemble pour trier. Comment les lignes sont-elles récupérées et comment l’ordre de tri est-il dérivé?
+----+---------+
| id | name |
+----+---------+
| 1 | stan |
| 2 | kyle |
| 3 | kenny |
| 4 | cartman |
+----+---------+
SELECT * FROM mytable WHERE id IN (3,2,1,4) ORDER BY FIELD(id,3,2,1,4)
La requête ci-dessus entraînera
+----+---------+
| id | name |
+----+---------+
| 3 | kenny |
| 2 | kyle |
| 1 | stan |
| 4 | cartman |
+----+---------+
quelque chose de similaire à dire ORDER BY 3, 2, 1, 4
DES QUESTIONS
- Comment ça marche en interne?
- Comment MySQL obtient-il les lignes et calcule-t-il l'ordre de tri?
- Comment MySQL sait-il qu'il doit trier par la colonne id?
SELECT *, FIELD(id,3,2,1,4) AS f FROM mytable WHERE id IN (3,2,1,4);
Ajoutez ensuiteORDER BY f
ouORDER BY FIELD(id,3,2,1,4)
et essayez à nouveau.Réponses:
Pour le compte rendu
devrait fonctionner aussi bien parce que vous n'avez pas à commander la liste dans la
WHERE
clauseQuant à la façon dont cela fonctionne,
FIELD () est une fonction qui renvoie la position d'index d'une liste délimitée par des virgules si la valeur recherchée existe.
Les
ORDER BY
valeurs sont évaluées par ce que FIELD () renvoieVous pouvez créer toutes sortes de commandes fantaisies
Par exemple, en utilisant le IF () fonction
Les 4 premiers identifiants apparaîtront en haut de la liste. Sinon, ils apparaîtront en bas. Pourquoi?
Dans le
ORDER BY
, vous obtenez 0 ou 1.Retournons-le avec DESC dans la première colonne
Dans le
ORDER BY
, vous obtenez toujours 0 ou 1.VOTRE QUESTION RÉELLE
Si vous voulez sérieusement des problèmes internes à ce sujet, passez aux pages 189 et 192 du livre.
pour une vraie plongée profonde.
En substance, il existe une classe C ++ appelée
ORDER *order
(l'ORDER BY
arbre d'expression). DansJOIN::prepare
,*order
est utilisé dans une fonction appeléesetup_order()
. Pourquoi au milieu de laJOIN
classe? Chaque requête, même une requête sur une seule table, est toujours traitée comme une jointure (voir mon post. Existe-t-il une différence d'exécution entre une condition JOIN et une condition WHERE? )Le code source pour tout cela est
sql/sql_select.cc
Évidemment, l’
ORDER BY
arbre va contenir l’évaluation deFIELD(id,3,2,1,4)
. Ainsi, les nombres 0,1,2,3,4 sont les valeurs en train d'être triées en portant une référence à la ligne concernée.la source
N
valeurs dans les deuxIN
etFIELD
. Dans cet exempleN=4
. Dois-je bien comprendre que cette requête va effectuer au moins des~N^2
opérations. Parce que chaqueFIELD
calcul fait des~N
comparaisons une fois pour chaque ligne. Si c'est le cas, c'est assez lent pour les grosN
Peut-être que ce n'est pas une très bonne approche?FIELD()
fonction doit être uneO(1)
opération carFIELD()
a un index numériqueid
. Donc, je ne vois rien d'autre queO(n)
basé sur des lignes. Je ne voisFIELD()
aucune opération itérative commeGREATEST()
il faudrait.FIELD
a desN
arguments avec lesquels comparer, alors il exécutera desN
comparaisons. Sinon, comment va-t-il comparer un nombre avec d'N
autres si on ne le fait pasO(N)
? La seule possibilité à laquelle je puisse penser est une sorte d'optimisation via une structure de données spéciale telle qu'un hachage ou une arborescence d'arguments. En fait, je sais queIN
cela a une telle optimisation. Je ne sais pas pourFIELD
. Qu'entendez-vous par "index numérique"?Peut-être que ce sera trop loin du code réel, donc pas assez bas de ce que vous vouliez:
Lorsque MySQL ne peut pas utiliser index pour extraire les données dans un ordre trié, il crée une table / un ensemble de résultats temporaire avec toutes les colonnes sélectionnées et des données supplémentaires - une de celles-ci est une sorte de colonne permettant de stocker les résultats de la valeur de l'expression ORDER BY pour chaque ligne - puis il envoie cette table tmp à un rutine "filesort" avec des informations sur la colonne à trier. Après cela, les lignes sont triées de manière à pouvoir les sélectionner une à une et renvoyer les colonnes sélectionnées.
la source
FIELD
fonction est calculée. Je crains que cela puisse avoir un impact significatif sur les performances.