Supposons que vous ayez le tableau et les données suivants:
create table t (
k int,
v int,
index k(k)
) engine=memory;
insert into t (k, v)
values (10, 1),
(10, 2),
(10, 3);
Lors de l'émission select * from t where k = 10
sans order by
clause, comment MySQL trie-t-il les enregistrements par défaut?
Republication ma réponse à une question similaire concernant SQL Server:
Dans le monde SQL, l'ordre n'est pas une propriété inhérente d'un ensemble de données. Ainsi, vous n'obtenez aucune garantie de votre SGBDR que vos données reviendront dans un certain ordre - ou même dans un ordre cohérent - sauf si vous interrogez vos données avec une clause ORDER BY.
Donc, pour répondre à votre question:
ORDER BY
. Faire autre chose, c'est vous préparer à des surprises importunes. C'est une propriété de tout SQL, pas seulement de MySQL. Le texte pertinent dans le spécification SQL-92 est:
Si une <clause order by> n'est pas spécifiée, l'ordre des lignes de Q dépend de l'implémentation.
Il y a des morceaux de texte similaires dans la spécification pour les curseurs.
L'ordre des lignes en l'absence de ORDER BY
la clause peut être:
L'insertion est désordonnée, chaotique, à l'arrivée. L'index qui est créé a l'ordre dans lequel les éléments sont insérés à l'emplacement approprié dans la liste chaînée qui est l'index. Pensez à une liste triplement liée pour un index, où vous avez un lien vers l'avant d'un élément d'index au suivant, un lien vers l'arrière pour les fins de traversée et d'intégrité, puis un ensemble de pointeurs vers les enregistrements réels dans le tableau qui correspondre à l'élément indexé en question.
Données réelles, chaotiques dans le stockage. Index associé aux données, commandé en stockage et en construction. L'extraction réelle des données, ordonnées ou non, dépend de la requête impliquée.
En ce qui concerne le moteur de stockage MEMORY , je m'attendrais à ce que l'ordre soit par ordre d'insertion car l'index par défaut la disposition est HASH
au lieu de BTREE
et aucun des aspects de la disposition d'index n'est utilisé. Puisque vous avez indexé k et k est la même valeur, toutes les clés entrent dans le même compartiment de hachage. Puisqu'il n'y a aucune raison de supposer une complexité supplémentaire pour remplir un compartiment de hachage, l'ordre d'insertion est le plus logique.
J'ai pris votre même exemple de table et de données et j'ai exécuté 30 INSERT
s et j'ai obtenu ceci:
mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.00 sec)
mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t values
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30 Duplicates: 0 Warnings: 0
mysql> select * from t;
+------+------+
| k | v |
+------+------+
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
+------+------+
30 rows in set (0.00 sec)
mysql>
J'ai décidé de tester en ajoutant deux valeurs différentes pour k: 10 et 11, j'ai obtenu ceci:
mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)
mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t values
-> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
-> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30 Duplicates: 0 Warnings: 0
mysql> select * from t;
+------+------+
| k | v |
+------+------+
| 11 | 1 |
| 11 | 2 |
| 11 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 11 | 1 |
| 11 | 2 |
| 11 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
+------+------+
30 rows in set (0.00 sec)
mysql>
Ressemble à l'ordre d'insertion. k = 11 était la première clé hachée puis 10. Qu'en est-il d'insérer 10 d'abord au lieu de 11? Voici ce que j'ai obtenu:
mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)
mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t values
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
-> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
-> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30 Duplicates: 0 Warnings: 0
mysql> select * from t;
+------+------+
| k | v |
+------+------+
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 11 | 1 |
| 11 | 2 |
| 11 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 11 | 1 |
| 11 | 2 |
| 11 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
| 10 | 1 |
| 10 | 2 |
| 10 | 3 |
+------+------+
30 rows in set (0.00 sec)
mysql>
C'est unanime !!! ORDRE D'INSERTION est la réponse.
Sidenotes sur l'utilisation des index pour le moteur de stockage MEMORY
Les recherches de plage pour MEMORY auraient des performances horribles comparables.
Lors de la création d'un index, vous pouvez spécifier USING BTREE
clause avec la définition de l'index. Cela améliorerait les choses pour les requêtes de plage.
La recherche d'une ligne spécifique produira le même résultat en termes de performances avec HASH
ou BTREE
.
MISE À JOUR 2011-09-22 11:18 EDT
J'ai appris quelque chose d'intéressant aujourd'hui. J'ai lu le lien fourni par @ Laurynas Biveinis de Percona: Le lien Percona dit quelque chose sur les tables MEMORY pour MySQL 5.5.15:
Ordre des lignes
En l'absence de ORDER BY, les enregistrements peuvent être retournés dans un ordre différent de celui de la précédente mise en œuvre de MEMORY. Ce n'est pas un bug. Toute application s'appuyant sur une commande spécifique sans clause ORDER BY peut fournir des résultats inattendus. Une commande spécifique sans ORDER BY est un effet secondaire d'une implémentation d'un moteur de stockage et d'un optimiseur de requête qui peut et va changer entre les versions mineures de MySQL.
Ce fut un bon lien pour moi de voir aujourd'hui. La réponse que j'ai donnée a démontré que la table que j'ai chargée a été récupérée dans l'ordre que j'attendais AUJOURD'HUI dans MySQL 5.5.12. Comme vient de le souligner Percona et @ Laurynas Biveinis , il n'y a aucune garantie dans une autre version mineure.
Donc, plutôt que d'essayer de défendre ma réponse, je préfère promouvoir la réponse de @ Laurynas Biveinis car il s'agit des informations les plus récentes. Bravo et chapeau pour @ Laurynas Biveinis . Je voudrais également remercier @ eevar pour avoir poliment souligné de ne pas promouvoir les réponses spécifiques aux versions des questions. Ils ont tous les deux obtenu mon vote positif aujourd'hui.