Het korte antwoord is ja, de primaire sleutel heeft een volgorde, alle indexen hebben een volgorde en een primaire sleutel is gewoon een unieke index.
Zoals u terecht heeft gezegd, moet u er niet op vertrouwen dat gegevens worden geretourneerd in de volgorde waarin de gegevens zijn opgeslagen, de optimiser is vrij om deze in elke gewenste volgorde te retourneren, en dit is afhankelijk van het queryplan. Ik zal echter proberen uit te leggen waarom uw zoekopdracht al 12 jaar werkt.
Uw geclusterde index is slechts uw tabelgegevens en uw clustersleutel definieert de volgorde waarin deze is opgeslagen. De gegevens worden opgeslagen op het blad en de clusteringsleutel helpt de root (en tussenliggende noten) als aanwijzers om snel naar de rechterblad om de gegevens op te halen. Een niet-geclusterde index is een zeer vergelijkbare structuur, maar het laagste niveau bevat gewoon een verwijzing naar de juiste positie op het blad van de geclusterde index.
In MySQL zijn de primaire sleutel en de geclusterde index synoniem, dus de primaire sleutel is geordend, maar het zijn in wezen twee verschillende dingen. In andere DBMS kunt u zowel een primaire sleutel als een geclusterde index definiëren. Wanneer u dit doet, wordt uw primaire sleutel een unieke niet-geclusterde index met een verwijzing naar de geclusterde index.
In de eenvoudigste bewoordingen kunt u zich een tabel voorstellen met een ID-kolom die de primaire sleutel is, en een andere kolom (A), uw B-Tree-structuur voor uw geclusterde index zou er ongeveer zo uitzien:
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 |
+-----------+ +-----------+ +-----------+
In werkelijkheid zullen de bladpagina's veel groter zijn, maar dit is slechts een demo. Elke pagina heeft ook een verwijzing naar de volgende pagina en de vorige pagina zodat u gemakkelijk door de boom kunt bladeren. Dus wanneer u een zoekopdracht uitvoert zoals:
SELECT ID, A
FROM T
WHERE ID > 5
LIMIT 1;
u scant een unieke index, dus het is zeer waarschijnlijk dat dit een sequentiële scan is. Zeer waarschijnlijk is echter niet gegarandeerd.
MySQL scant het Root-knooppunt, als er een potentiële overeenkomst is, gaat het verder naar de tussenliggende knooppunten, als de clausule zoiets was geweest als WHERE ID < 0
dan zou MySQL weten dat er geen resultaten waren zonder verder te gaan dan de root-node.
Zodra het naar het tussenliggende knooppunt gaat, kan het identificeren dat het op de tweede pagina moet beginnen (tussen 4 en 7) om te beginnen met zoeken naar een ID > 5
. Het scant dus achtereenvolgens het blad vanaf de tweede bladpagina, nadat de LIMIT 1
al is geïdentificeerd. het stopt zodra het een overeenkomst vindt (in dit geval 6) en retourneert deze gegevens van het blad. In zo'n eenvoudig voorbeeld lijkt dit gedrag betrouwbaar en logisch. Ik heb geprobeerd uitzonderingen te forceren door een ID-waarde te kiezen waarvan ik weet dat deze aan het einde van een leaf-pagina staat om te zien of de leaf in omgekeerde volgorde wordt gescand, maar ik heb dit gedrag tot nu toe niet kunnen produceren, dit betekent echter niet dat het zal niet gebeuren, of dat toekomstige releases van MySQL dit niet zullen doen in de scenario's die ik heb getest.
Kortom, voeg gewoon een bestelling toe op, of gebruik MIN(ID) en klaar. Ik zou niet te veel slaap verliezen als ik me in de innerlijke werking van de query-optimizer wilde verdiepen om te zien wat voor soort fragmentatie of gegevensbereiken nodig zouden zijn om de verschillende volgorde van de geclusterde index binnen het queryplan te observeren.