Kolejność rekordów zapewnia ORDER BY i tylko ORDER BY

Jeżeli polegamy na kolejności rekordów zwróconych przez polecenie SELECT, musimy dokładnie określić klauzulę ORDER BY.

Nie pisałbym o tym, gdyby nie pewien przypadek z którym się zetknąłem (oczywiście opis jest trochę uproszczony). Mamy tabelę TAB której kluczem głównym są pola A i B. Posiadamy też indeks po kluczu głównym - czyli po (A,B). Realizujemy wyszukiwanie w stylu

    SELECT ... FROM TAB WHERE A = ...

Autor programu nie umieścił klauzuli ORDER BY ale zakładał (z ważnymi konsekwencjami dla wyników działania programu), że zwracane wyniki są posortowane po B. I tak było! Oracle rozwiązując zapytanie decydował, że warto skorzystać z indeksu i jako efekt uboczny, zwracał rekordy w takiej kolejności w jakiej znajdowały się w indeksie. Program przeszedł wszelkie testy w różnych konfiguracjach etc.

Po bodajże roku produkcyjnego działania zdarzyło się, że Oracle miał pewne kłopoty z statystykami. Bodajże administrator w niewłaściwym momencie - gdy tablica była prawie pusta - wykonał ANALYZE TABLE ESTIMATE STATISTICS. W konsekwencji, rozwiązując opisane zapytanie, Oracle uznało, że nie warto korzystać z indeksu, bo bardziej opłaci się sekwencyjny przegląd całej tablicy (full table scan). Rekordy zostały zwrócone w dość przypadkowej kolejności a analiza przyczyn i usuwanie skutków błędu (który został zauważony dopiero po pewnym czasie) kosztowały sporo.

Powodów dla których Oracle może zmienić plan wykonania jest wiele, przeliczenie statystyk to tylko jeden z nich. Może pojawić się nowy indeks. Oracle może się próbować dopasować do zmienionego obciążenia (np. mniej/więcej miejsca w SGA, inne możliwości zrównoleglania zapytań). Nie jesteśmy w stanie wszystkiego przewidzieć! Jeśli kolejność rekordów jest istotna, musimy specyfikować ORDER BY.

Jest jeszcze wniosek dodatkowy: żadne testy nie zastąpią review kodu przeprowadzonego przez inną niż autor i w miarę doświadczoną osobę.

komentarze obsługiwane przez Disqus