Natknąłem się na to pytanie w rozmowie na Twitterze z Lukasem Ederem .
Chociaż poprawnym działaniem byłoby zastosowanie klauzuli ORDER BY w najbardziej zewnętrznym zapytaniu, ponieważ tutaj nie używamy DISTINCT, GROUP BY, JOIN ani żadnej innej klauzuli WHERE w najbardziej zewnętrznym zapytaniu, dlaczego RDBMS po prostu nie przekaże przychodzące dane, które zostały posortowane według wewnętrznego zapytania?
SELECT *
FROM (
SELECT * FROM table ORDER BY time DESC
) AS t
Uruchamiając ten przykład na PostgreSQL, otrzymujesz co najmniej ten sam plan wykonania zarówno dla wewnętrznego zapytania, jak i tego przykładu tabeli pochodnej, a także ten sam zestaw wyników.
Zakładam więc, że Planista po prostu odrzuci najbardziej zewnętrzne zapytanie, ponieważ jest ono zbędne lub po prostu przechodzi przez wyniki z wewnętrznej tabeli.
Czy ktoś uważa, że tak nie jest?
źródło
ORDER BY
prowadzi do innej optymalizacji dla grupowego maks .Odpowiedzi:
Większość baz danych jest dość jasna na temat faktu, że
ORDER BY
w podzapytaniu jest albo:TOP
lubOFFSET .. FETCH
)OFFSET .. FETCH
lubLIMIT
)Oto przykład z podręcznika DB2 LUW (wyróżnienie moje)
Sformułowanie jest dość wyraźne, podobnie jak PostgreSQL :
Z tej specyfikacji można
ORDER BY
wywnioskować, że każde uporządkowanie wynikające z klauzuli w tabeli pochodnej jest jedynie przypadkowe i może przypadkowo pasować do oczekiwanej kolejności (co robi w większości baz danych w trywialnym przykładzie), ale nierozsądne byłoby polegać na to.Uwaga dodatkowa na temat DB2:
W szczególności DB2 ma mniej znaną funkcję o nazwie
ORDER BY ORDER OF <table-designator>
, której można użyć w następujący sposób:W tym konkretnym przypadku kolejność tabeli pochodnej może zostać ponownie wyraźnie użyta w najbardziej zewnętrznym SELECT
Uwaga dodatkowa na temat Oracle:
Od lat praktyką w Oracle jest stosowanie
OFFSET
paginacji przy użyciuROWNUM
, którą można racjonalnie obliczyć dopiero po zamówieniu tabeli pochodnej:Można zasadnie oczekiwać, że przynajmniej w obecności
ROWNUM
zapytania przyszłe wersje Oracle nie złamią tego zachowania, aby nie złamać prawie całej dotychczasowej wersji Oracle SQL, która nie została jeszcze przeniesiona do znacznie bardziej pożądanej i czytelna standardowaOFFSET .. FETCH
składnia SQL :źródło
Meaningless: E.g. PostgreSQL
powinien być naprawdę: „niewiarygodne”, ponieważ ma coś znaczyć. Wiersze są sortowane w wewnętrznym zapytaniu, a ta kolejność jest utrzymywana na zewnętrznym poziomie zapytania, chyba że zalecono inaczej lub zmiana kolejności jest odpowiednia dla dodatkowych operacji. Nawet jeśli jest to tylko szczegół implementacji, nie jest to bez znaczenia. Można tego użyć do posortowanego wejścia do agregacji funkcji. Podręcznik nawet wskazuje tyle samo:Alternatively, supplying the input values from a sorted subquery will usually work.
ORDER BY
w ogóle nie.Tak. Bez
ORDER BY
klauzuli kolejność wyjściowa jest niezdefiniowana, a planista zapytań mieści się w zakresie jego kompetencji, aby założyć, że znasz to i rozumiesz.Może zdecydować, że ponieważ zapytanie zewnętrzne nie określa kolejności, może porzucić porządek w zapytaniu wewnętrznym, aby uniknąć operacji sortowania, szczególnie jeśli nie ma indeksu klastrowego lub w ogóle indeksu do obsługi porządkowania. Jeśli nie teraz , może to zrobić w przyszłych wersjach.
Nigdy nie polegaj na nieokreślonym zachowaniu. Jeśli potrzebujesz konkretnego zamówienia, podaj
ORDER BY
klauzulę w odpowiednim miejscu.źródło
TOP 100%
więc bieżące zapytanie nie jest przenośne, powinno to być priorytetem dla twojego projektu. Ponieważ Postgres przestrzega kolejności w wewnętrznym zapytaniu, nie oznacza to, że zawsze będzie to robić w przyszłości (lub w rzeczywistości starsze wersje), więc na wszelki wypadek powinieneś unikać polegania na zachowaniuORDER BY
to MariaDB: Dlaczego ORDER BY w podzapytaniu FROM jest ignorowany?To właśnie problem z nieokreślonym zachowaniem - działa dla ciebie, działa dla mnie, formatuje HDD w prod;)
Możemy cofnąć się o krok i powiedzieć, że w pewnym sensie masz rację - nie ma ziemskiego powodu, dla którego rozsądny system RDBMS zmieniłby rzędy w wewnętrznej selekcji. Ale nie jest to gwarantowane - co oznacza, że w przyszłości może być jakiś powód, a sprzedawcy mogą to zrobić. Oznacza to, że każdy kod, który opiera się na tym zachowaniu, jest zdany na zmianę, którą może wprowadzić sprzedawca, którego nie byłby zobowiązany do opublikowania, ponieważ nie jest to przełomowa zmiana w stosunku do POV API.
źródło
SELECT
nieORDER BY
jest niedeterministyczny i nie tylko teoretycznie, albo dlatego, że dane się zmieniły)Odpowiedź dla wszystkich obecnie istniejących wersji Postgres (które testowałeś) brzmi: Nie - dla tego konkretnego zapytania. Kolejność sortowania jest gwarantowana.
Ludzie korzystający z serwera SQL nie będą się z tym czuć komfortowo, ponieważ Microsoft nawet nie zezwala
ORDER BY
na podzapytania. Mimo to kolejność sortowania jest gwarantowana w przypadku tego prostego zapytania w Postgres.ORDER BY
jest stosowane w podzapytaniu, a zapytanie zewnętrzne nie robi niczego, co mogłoby zmienić kolejność.Podręcznik nawet wskazuje tyle samo w rozdziale Funkcje agregujące :
Zauważ, że jest to prawdą tylko wtedy, gdy zewnętrzne poziomy zapytań nie dodają operacji, które mogłyby zmienić kolejność. Jest to więc „gwarantowane” tylko w prostym przypadku i nie jest ono wspierane przez standard SQL. Postgres może bezpłatnie zmieniać kolejność, jeśli jest to odpowiednie do dodatkowych operacji. W razie wątpliwości dodaj kolejną
ORDER BY
do zewnętrznejSELECT
. (W takim przypadku wewnętrznyORDER BY
dźwięk byłby nadmiarowy dla tego prostego zapytania).źródło
"table"
nie jest to prosta tabela bazowa, ale złożony widok lub tabela podzielona na partycje? Czy to prawda, że plan ma również wykonanie równoległe? Czy to prawda również w Postgres 10? (Pytam tylko, nie jestem pewien na odpowiedź na którekolwiek z tych pytań.)