Anche se è bene chiedersi come si possa spiegare che spesso si vede lo stesso ordine, vorrei sottolineare che non è mai una buona idea fare affidamento sull'ordine implicito causato dalla particolare implementazione del motore di database sottostante. In altre parole, è bello sapere perché, ma non dovresti mai fare affidamento su di esso. Per MS SQL, l'unica cosa che fornisce le righe in modo affidabile in un certo ordine è un esplicito ORDER BY
clausola.
Non solo diversi RDMBS-es si comportano in modo diverso, una particolare istanza potrebbe comportarsi in modo diverso a causa di un aggiornamento (patch). Non solo, anche lo stato del software RDBMS può avere un impatto:un database "caldo" si comporta in modo diverso da uno "freddo", una tabella piccola si comporta in modo diverso rispetto a uno grande.
Anche se disponi di informazioni di base sull'implementazione (es:"c'è un indice cluster, quindi è probabile che i dati vengano restituiti in base all'ordine dell'indice cluster"), c'è sempre la possibilità che ci sia un altro meccanismo che non possiedi Non so questo fa sì che le righe vengano restituite in un ordine diverso (ex1:"se un'altra sessione ha appena eseguito una scansione completa della tabella con un esplicito ORDER BY
il set di risultati potrebbe essere stato memorizzato nella cache; una successiva scansione completa tenterà di restituire le righe dalla cache"; ex2:"a GROUP BY
può essere implementato ordinando i dati, influenzando così l'ordine in cui le righe vengono restituite"; ex3:"Se le colonne selezionate sono tutte in un indice secondario che è già memorizzato nella cache, il motore può scansionare l'indice secondario anziché la tabella, molto probabilmente restituendo le righe in base all'ordine dell'indice secondario").
Ecco un test molto semplice che illustra alcuni dei miei punti.
Innanzitutto, avvia il server SQL (sto usando 2008). Crea questa tabella:
create table test_order (
id int not null identity(1,1) primary key
, name varchar(10) not null
)
Esamina la tabella e verifica che è stato creato un indice cluster per supportare la primary key
sull'id
colonna. Ad esempio, in sql Server Management Studio, puoi utilizzare la visualizzazione ad albero e passare alla cartella degli indici sotto la tabella. Lì dovresti vedere un indice, con un nome come:PK__test_ord__3213E83F03317E3D (Clustered)
Inserisci la prima riga con questa affermazione:
insert into test_order(name)
select RAND()
Inserisci più righe ripetendo questa affermazione 16 volte:
insert into test_order(name)
select RAND()
from test_order
Ora dovresti avere 65536 righe:
select COUNT(*)
from test_order
Ora seleziona tutte le righe senza utilizzare un ordine per:
select *
from test_order
Molto probabilmente, i risultati verranno restituiti in base all'ordine della chiave primaria (sebbene non vi sia alcuna garanzia). Ecco il risultato che ho ottenuto (che in effetti è in ordine di chiave primaria):
# id name
1 1 0.605831
2 2 0.517251
3 3 0.52326
. . .......
65536 65536 0.902214
(il # non è una colonna ma la posizione ordinale della riga nel risultato)
Ora, crea un indice secondario su name
colonna:
create index idx_name on test_order(name)
Seleziona tutte le righe, ma recupera solo il name
colonna:
select name
from test_order
Molto probabilmente i risultati verranno restituiti in base all'ordine dell'indice secondario idx_name, poiché la query può essere risolta eseguendo solo la scansione dell'indice (cioè idx_name
è una copertura indice). Ecco il risultato che ho ottenuto, che in effetti è in ordine di name
.
# name
1 0.0185732
2 0.0185732
. .........
65536 0.981894
Ora, seleziona di nuovo tutte le colonne e tutte le righe:
select *
from test_order
Ecco il risultato che ho ottenuto:
# id name
1 17 0.0185732
2 18 0.0185732
3 19 0.0185732
... .. .........
come puoi vedere, molto diverso dalla prima volta che abbiamo eseguito questa query. (Sembra che le righe siano ordinate in base all'indice secondario, ma non ho una spiegazione del perché dovrebbe essere così).
Ad ogni modo, la linea di fondo è:non fare affidamento sull'ordine implicito. Puoi pensare a spiegazioni sul perché un particolare ordine può essere osservato, ma anche in questo caso non puoi sempre prevederlo (come in quest'ultimo caso) senza avere una conoscenza approfondita dell'implementazione e dello stato di runtime.