Mysql
 sql >> Database >  >> RDS >> Mysql

È una chiave primaria MySQL già in una sorta di ordine predefinito

La risposta breve è sì, la chiave primaria ha un ordine, tutti gli indici hanno un ordine e una chiave primaria è semplicemente un indice univoco.

Come hai giustamente affermato, non dovresti fare affidamento sul fatto che i dati vengano restituiti nell'ordine in cui i dati sono archiviati, l'ottimizzatore è libero di restituirli nell'ordine che preferisce e questo dipenderà dal piano di query. Cercherò comunque di spiegare perché la tua richiesta ha funzionato per 12 anni.

Il tuo indice cluster è solo i dati della tua tabella e la tua chiave di clustering definisce l'ordine in cui è archiviato. I dati sono archiviati sulla foglia e la chiave di clustering aiuta la radice (e le note intermedie) ad agire come puntatori per arrivare rapidamente al foglia destra per recuperare i dati. Un indice non cluster è una struttura molto simile, ma il livello più basso contiene semplicemente un puntatore alla posizione corretta sulla foglia dell'indice cluster.

In MySQL la chiave primaria e l'indice cluster sono sinonimi, quindi la chiave primaria è ordinata, tuttavia sono fondamentalmente due cose diverse. In altri DBMS puoi definire sia una chiave primaria che un indice cluster, quando lo fai la tua chiave primaria diventa un indice non cluster univoco con un puntatore all'indice cluster.

In parole povere puoi immaginare una tabella con una colonna ID che è la chiave primaria e un'altra colonna (A), la tua struttura B-Tree per il tuo indice cluster sarebbe qualcosa del tipo:

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 realtà le pagine foglia saranno molto più grandi, ma questa è solo una demo. Ogni pagina ha anche un puntatore alla pagina successiva e alla pagina precedente per facilitare l'attraversamento dell'albero. Quindi, quando esegui una query del tipo:

SELECT ID, A
FROM T
WHERE ID > 5
LIMIT 1;

stai eseguendo la scansione di un indice univoco, quindi è molto probabile che si tratti di una scansione sequenziale. Molto probabilmente non è garantito però.

MySQL eseguirà la scansione del nodo Root, se esiste una potenziale corrispondenza si sposterà sui nodi intermedi, se la clausola fosse stata qualcosa del tipo WHERE ID < 0 quindi MySQL saprebbe che non ci sono risultati senza andare oltre il nodo radice.

Una volta passato al nodo intermedio può identificare che deve iniziare dalla seconda pagina (tra 4 e 7) per iniziare a cercare un ID > 5 . Quindi eseguirà la scansione sequenziale della foglia partendo dalla seconda pagina foglia, avendo già identificato il LIMIT 1 si fermerà una volta trovata una corrispondenza (in questo caso 6) e restituirà questi dati dalla foglia. In un esempio così semplice questo comportamento sembra essere affidabile e logico. Ho provato a forzare le eccezioni scegliendo un valore ID che so essere alla fine di una pagina foglia per vedere se la foglia verrà scansionata nell'ordine inverso, ma finora non sono stato in grado di produrre questo comportamento, questo non significa comunque non accadrà o che le versioni future di MySQL non lo faranno negli scenari che ho testato.

In breve, basta aggiungere un ordine o utilizzare MIN(ID) e il gioco è fatto. Non perderei troppo sonno cercando di approfondire il funzionamento interno di Query Optimizer per vedere che tipo di frammentazione o intervalli di dati sarebbero necessari per osservare un diverso ordinamento dell'indice cluster all'interno del piano di query.