La respuesta corta es sí, la clave principal tiene un orden, todos los índices tienen un orden y una clave principal es simplemente un índice único.
Como ha dicho correctamente, no debe confiar en que los datos se devuelvan en el orden en que se almacenan, el optimizador es libre de devolverlos en el orden que desee, y esto dependerá del plan de consulta. Sin embargo, intentaré explicar por qué su consulta ha funcionado durante 12 años.
Su índice agrupado es solo los datos de su tabla, y su clave de agrupamiento define el orden en que se almacena. Los datos se almacenan en la hoja, y la clave de agrupamiento ayuda a la raíz (y las notas intermedias) a actuar como punteros para llegar rápidamente al hoja derecha para recuperar los datos. Un índice no agrupado es una estructura muy similar, pero el nivel más bajo simplemente contiene un puntero a la posición correcta en la hoja del índice agrupado.
En MySQL, la clave principal y el índice agrupado son sinónimos, por lo que la clave principal está ordenada, sin embargo, son fundamentalmente dos cosas diferentes. En otros DBMS, puede definir tanto una clave principal como un índice agrupado, cuando hace esto, su clave principal se convierte en un índice no agrupado único con un puntero de regreso al índice agrupado.
En sus términos más simples, puede imaginar una tabla con una columna de ID que es la clave principal y otra columna (A), su estructura B-Tree para su índice agrupado sería algo así como:
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 realidad, las páginas de hoja serán mucho más grandes, pero esto es solo una demostración. Cada página también tiene un puntero a la página siguiente y a la página anterior para facilitar el desplazamiento por el árbol. Así que cuando haces una consulta como:
SELECT ID, A
FROM T
WHERE ID > 5
LIMIT 1;
está escaneando un índice único, por lo que es muy probable que sea un escaneo secuencial. Sin embargo, es muy probable que no esté garantizado.
MySQL escaneará el nodo raíz, si hay una coincidencia potencial, pasará a los nodos intermedios, si la cláusula hubiera sido algo así como WHERE ID < 0
entonces MySQL sabría que no hubo resultados sin ir más allá del nodo raíz.
Una vez que pasa al nodo intermedio, puede identificar que necesita comenzar en la segunda página (entre 4 y 7) para comenzar a buscar un ID > 5
. Por lo tanto, escaneará secuencialmente la hoja comenzando en la página de la segunda hoja, habiendo identificado ya el LIMIT 1
se detendrá una vez que encuentre una coincidencia (en este caso, 6) y devolverá estos datos de la hoja. En un ejemplo tan simple, este comportamiento parece ser confiable y lógico. Intenté forzar excepciones eligiendo un valor de ID que sé que está al final de una página de hoja para ver si la hoja se escaneará en el orden inverso, pero hasta ahora no he podido producir este comportamiento, sin embargo, esto no significa no sucederá, o que las versiones futuras de MySQL no harán esto en los escenarios que he probado.
En resumen, solo agregue un pedido por, o use MIN (ID) y listo. No perdería demasiado el sueño tratando de profundizar en el funcionamiento interno del optimizador de consultas para ver qué tipo de fragmentación o rangos de datos serían necesarios para observar un orden diferente del índice agrupado dentro del plan de consulta.