Chociaż dobrze jest zastanowić się, jak można wyjaśnić, że często widzisz tę samą kolejność, chciałbym zaznaczyć, że nigdy nie jest dobrym pomysłem poleganie na niejawnej kolejności spowodowanej konkretną implementacją bazowego silnika bazy danych. Innymi słowy, miło jest wiedzieć dlaczego, ale nigdy nie powinieneś na tym polegać. W przypadku MS SQL jedyną rzeczą, która niezawodnie dostarcza wiersze w określonej kolejności, jest jawne ORDER BY
klauzula.
Nie tylko różne RDMBS-y zachowują się inaczej, ale jedna konkretna instancja może zachowywać się inaczej z powodu aktualizacji (poprawki). Mało tego, nawet stan oprogramowania RDBMS może mieć wpływ:„ciepła” baza danych zachowuje się inaczej niż „zimna”, mała tabela zachowuje się inaczej niż duża.
Nawet jeśli masz podstawowe informacje o implementacji (np.:„istnieje indeks klastrowy, więc prawdopodobnie dane zostaną zwrócone według kolejności indeksu klastrowego”), zawsze istnieje możliwość, że istnieje inny mechanizm, którego nie używasz Wiedza o tym powoduje, że wiersze są zwracane w innej kolejności (np.:"jeśli inna sesja właśnie wykonała pełne skanowanie tabeli z jawnym ORDER BY
zestaw wyników mógł zostać zbuforowany; kolejne pełne skanowanie będzie próbowało zwrócić wiersze z pamięci podręcznej"; ex2:"a GROUP BY
może być realizowane poprzez sortowanie danych, co ma wpływ na kolejność zwracania wierszy”; przykład3:„Jeśli wybrane kolumny znajdują się w indeksie wtórnym, który jest już zbuforowany w pamięci, silnik może skanować indeks wtórny zamiast tabeli, najprawdopodobniej zwraca wiersze według kolejności indeksu wtórnego").
Oto bardzo prosty test, który ilustruje niektóre z moich punktów.
Najpierw uruchom serwer SQL (używam 2008). Utwórz tę tabelę:
create table test_order (
id int not null identity(1,1) primary key
, name varchar(10) not null
)
Sprawdź tabelę i zobacz, że utworzono indeks klastrowy do obsługi primary key
na id
kolumna. Na przykład w sql server management studio można użyć widoku drzewa i przejść do folderu indexs pod tabelą. Powinieneś tam zobaczyć jeden indeks o nazwie:PK__test_ord__3213E83F03317E3D (Clustered)
Wstaw pierwszy wiersz z następującym stwierdzeniem:
insert into test_order(name)
select RAND()
Wstaw więcej wierszy, powtarzając to stwierdzenie 16 razy:
insert into test_order(name)
select RAND()
from test_order
Powinieneś teraz mieć 65536 wierszy:
select COUNT(*)
from test_order
Teraz wybierz wszystkie wiersze bez użycia kolejności:
select *
from test_order
Najprawdopodobniej wyniki zostaną zwrócone według kolejności klucza podstawowego (chociaż nie ma gwarancji). Oto wynik, który otrzymałem (który rzeczywiście jest uporządkowany według klucza podstawowego):
# id name
1 1 0.605831
2 2 0.517251
3 3 0.52326
. . .......
65536 65536 0.902214
(# nie jest kolumną, ale porządkową pozycją wiersza w wyniku)
Teraz utwórz dodatkowy indeks na name
kolumna:
create index idx_name on test_order(name)
Zaznacz wszystkie wiersze, ale pobierz tylko name
kolumna:
select name
from test_order
Najprawdopodobniej wyniki zostaną zwrócone według kolejności indeksu dodatkowego idx_name, ponieważ zapytanie może zostać rozwiązane tylko poprzez skanowanie indeksu (np. idx_name
to przykrycie indeks). Oto wynik, który otrzymałem, rzeczywiście według kolejności name
.
# name
1 0.0185732
2 0.0185732
. .........
65536 0.981894
Teraz ponownie zaznacz wszystkie kolumny i wszystkie wiersze:
select *
from test_order
Oto wynik, który otrzymałem:
# id name
1 17 0.0185732
2 18 0.0185732
3 19 0.0185732
... .. .........
jak widać, zupełnie inaczej niż przy pierwszym uruchomieniu tego zapytania. (Wygląda na to, że wiersze są uporządkowane według indeksu wtórnego, ale nie mam wyjaśnienia, dlaczego tak powinno być).
W każdym razie najważniejsze jest - nie polegaj na ukrytym porządku. Możesz wymyślić wyjaśnienia, dlaczego można zaobserwować określoną kolejność, ale nawet wtedy nie zawsze możesz ją przewidzieć (jak w tym drugim przypadku) bez gruntownej wiedzy na temat implementacji i stanu środowiska wykonawczego.