La réponse courte est oui, la clé primaire a un ordre, tous les index ont un ordre et une clé primaire est simplement un index unique.
Comme vous l'avez dit à juste titre, vous ne devez pas compter sur le fait que les données sont renvoyées dans l'ordre dans lequel elles sont stockées, l'optimiseur est libre de les renvoyer dans l'ordre de son choix, et cela dépendra du plan de requête. Je vais cependant essayer d'expliquer pourquoi votre requête a fonctionné pendant 12 ans.
Votre index clusterisé est juste vos données de table, et votre clé de clustering définit l'ordre dans lequel il est stocké. Les données sont stockées sur la feuille, et la clé de clustering aide la racine (et les notes intermédiaires) à agir comme des pointeurs pour accéder rapidement à la feuille de droite pour récupérer les données. Un index non clusterisé est une structure très similaire, mais le niveau le plus bas contient simplement un pointeur vers la position correcte sur la feuille de l'index clusterisé.
Dans MySQL, la clé primaire et l'index clusterisé sont synonymes, donc la clé primaire est ordonnée, mais ce sont fondamentalement deux choses différentes. Dans d'autres SGBD, vous pouvez définir à la fois une clé primaire et un index clusterisé. Lorsque vous faites cela, votre clé primaire devient un index non clusterisé unique avec un pointeur vers l'index clusterisé.
Dans ses termes les plus simples, vous pouvez imaginer une table avec une colonne ID qui est la clé primaire et une autre colonne (A), votre structure B-Tree pour votre index clusterisé ressemblerait à :
Root Node
+---+
| 1 |
+---+
Intermediate Nodes
+---+ +---+ +---+
| 1 | | 4 | | 7 |
+---+ +---+ +---+
Leaf
+-----------+ +-----------+ +-----------+
ID -> | 1 | 2 | 3 | | 4 | 5 | 6 | | 7 | 8 | 9 |
A -> | A | B | C | | D | E | F | | G | H | I |
+-----------+ +-----------+ +-----------+
En réalité, les pages feuilles seront beaucoup plus grandes, mais ce n'est qu'une démo. Chaque page a également un pointeur vers la page suivante et la page précédente pour faciliter la navigation dans l'arborescence. Ainsi, lorsque vous faites une requête comme :
SELECT ID, A
FROM T
WHERE ID > 5
LIMIT 1;
vous analysez un index unique, il est donc très probable qu'il s'agisse d'une analyse séquentielle. Très probablement, ce n'est pas garanti.
MySQL analysera le nœud racine, s'il y a une correspondance potentielle, il passera aux nœuds intermédiaires, si la clause avait été quelque chose comme WHERE ID < 0
alors MySQL saurait qu'il n'y avait aucun résultat sans aller plus loin que le nœud racine.
Une fois qu'il passe au nœud intermédiaire, il peut identifier qu'il doit commencer sur la deuxième page (entre 4 et 7) pour commencer à rechercher un ID > 5
. Il va donc scanner séquentiellement le feuillet à partir de la deuxième page feuillet, ayant déjà identifié le LIMIT 1
il s'arrêtera une fois qu'il trouvera une correspondance (dans ce cas 6) et renverra ces données à partir de la feuille. Dans un exemple aussi simple, ce comportement semble être fiable et logique. J'ai essayé de forcer des exceptions en choisissant une valeur d'ID dont je sais qu'elle se trouve à la fin d'une page feuille pour voir si la feuille sera scannée dans l'ordre inverse, mais jusqu'à présent, je n'ai pas été en mesure de produire ce comportement, cela ne signifie cependant pas cela n'arrivera pas, ou que les futures versions de MySQL ne le feront pas dans les scénarios que j'ai testés.
En bref, ajoutez simplement une commande par, ou utilisez MIN (ID) et finissez-en. Je ne perdrais pas trop de temps à essayer de me plonger dans le fonctionnement interne de l'optimiseur de requête pour voir quel type de fragmentation ou de plages de données serait nécessaire pour observer un ordre différent de l'index clusterisé dans le plan de requête.