Dlaczego ORDER BY nie należy do widoku?

51

I zrozumieć , że nie można mieć ORDER BY w widoku. (Przynajmniej w SQL Server 2012, z którym pracuję)

Rozumiem również, że „poprawnym” sposobem sortowania widoku jest umieszczenie ORDER BYwokół SELECTinstrukcji, która wyświetla zapytanie.

Ale będąc stosunkowo nowym w praktycznym języku SQL i zastosowaniach widoków, chciałbym zrozumieć, dlaczego tak się dzieje. Jeśli poprawnie śledziłem historię, było to kiedyś możliwe i zostało wyraźnie usunięte z SQL Server 2008 i tak dalej (nie podawaj mi dokładnej wersji).

Jednak najlepszym powodem, dla którego mogę wymyślić, dlaczego Microsoft usunął tę funkcję, jest to, że „widok jest nieposortowanym zbiorem danych”.

Zakładam, że istnieje dobry, logiczny powód, dla którego Widok powinien być nieposortowany. Dlaczego widok nie może być po prostu spłaszczonym zbiorem danych? Dlatego specjalnie un -sorted? Nie wydaje się trudne wymyślenie sytuacji, w których (przynajmniej dla mnie / IMHO) wydaje się całkowicie intuicyjne mieć uporządkowany widok.

ngmiceli
źródło
2
Pierwsza odpowiedź jest idealna. Proponuję, jeśli chcesz zamówić widok, dlaczego tego nie zrobisz. Wybierz [Kolumny] z [YourView] Zamów według [Kolumny]
Zane
Krótka odpowiedź: „Z tego samego powodu, dla którego ORDER BY nie należy do tabeli”.
ypercubeᵀᴹ

Odpowiedzi:

38

(Poza indeksowanymi widokami oczywiście).

Widok nie został zmaterializowany - dane nie są przechowywane, więc jak można je posortować? Widok jest trochę jak procedura składowana, która zawiera po prostu SELECTparametr bez parametrów ... nie przechowuje danych, po prostu zawiera definicję zapytania. Ponieważ różne odniesienia do widoku mogą wymagać sortowania danych na różne sposoby, sposób, w jaki to robisz - podobnie jak wybieranie z tabeli, która z definicji jest również nieposortowanym zbiorem wierszy - polega na uwzględnianiu kolejności według zapytania zewnętrznego .

Również, aby dać trochę wglądu w historię. Nigdy nie można wystawić ORDER BYwidoku bez uwzględnienia TOP. I w tym przypadku ORDER BYpodyktowano, które wiersze zostały uwzględnione TOP, a nie to, jak zostaną przedstawione. Tak się złożyło, że w SQL Server 2000, jeśli TOPbył 100 PERCENTlub {some number >= number of rows in the table}, optymalizator był dość uproszczony i ostatecznie stworzył plan z rodzajem, który pasowałby do TOP/ORDER BY. Ale takie zachowanie nigdy nie było gwarantowane ani udokumentowane - opierało się na obserwacji, co jest złym nawykiem . Kiedy pojawił się SQL Server 2005, to zachowanie zaczęło się „łamać” z powodu zmian w optymalizatorze, które doprowadziły do ​​użycia różnych planów i operatorów - między innymiTOP / ORDER BYzostałby całkowicie zignorowany, gdyby tak było TOP 100 PERCENT. Niektórzy klienci skarżyli się na to tak głośno, że Microsoft wydał flagę śledzenia, aby przywrócić stare zachowanie. Nie powiem ci, co to jest flaga, ponieważ nie chcę, abyś jej używał i chcę upewnić się, że intencja jest poprawna - jeśli chcesz przewidywalnej kolejności sortowania, użyj ORDER BYzewnętrznego zapytania.

Podsumowując i tak samo, aby wyjaśnić postawiony punkt: Microsoft niczego nie usunął . Ulepszyli produkt, a jako efekt uboczny to nieudokumentowane, niegwarantowane zachowanie stało się mniej niezawodne. Ogólnie uważam, że produkt jest do tego lepszy.

Aaron Bertrand
źródło
Tutaj wspomniano (w komentarzu), że TOPwykonuje operację kursora na zestawie wyników. Dlatego może mieć wyraźne zamówienie.
Tim Schmelter,
@ TimSchmelter, który nie pomaga, gdy optymalizator zobaczy TOP 100 PERCENT / ORDER BYi całkowicie usunie go z planu. Wypróbuj to.
Aaron Bertrand
To był tylko sidenote. Reszta komentarza i tak jest następująca: „Trik SELECT TOP x ma być przestarzały w przyszłej wersji SQL Server, więc najlepiej byłoby go w ogóle nie używać”.
Tim Schmelter,
@TimSchmelter to już brak operacji. Nie sądzę, że w najbliższym czasie przestanie działać w nowej wersji, ponieważ zepsuje zbyt wiele istniejącego kodu.
Aaron Bertrand
2
@ TimSchmelter tam kolejność nie mówi o kolejności wierszy, chodzi o kolejność kolumn w wierszu. W SQL Server zasadniczo nie mówimy o tym, że wiersz jest krotką, ponieważ fizyczna implementacja wiersza jest dla nas tak oczywista (tabela zawiera kolumny w kolejności, w której je zdefiniowałeś).
Aaron Bertrand
9

Jeśli pozwolono na sortowanie widoku, jaka powinna być tutaj kolejność wyników?

CREATE VIEW dbo.V1
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number ASC

GO

CREATE VIEW dbo.V2
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number DESC

GO

SELECT *
FROM   dbo.V1
       JOIN dbo.V2
         ON V1.number = V2.number 
Martin Smith
źródło
Nie rozumiem tego. Zamiast pisać widok bazy danych, możesz napisać normalne zapytanie SQL. Jaka powinna być kolejność wyniku w takim przypadku? dzięki
hqt
7

jedną z możliwości jest uniknięcie sprzecznych sortowań - jeśli widok sortuje według jednego zamówienia, a wybór w tym widoku sortuje według innego zamówienia (nie wiedząc o sortowaniu widoków), może wystąpić pogorszenie wydajności. Bezpieczniej jest więc pozostawić użytkownikowi obowiązek sortowania.

inny powód sortowania wiąże się z kosztami wydajności, więc po co karać wszystkich użytkowników widoku, gdy tylko niektórzy użytkownicy potrzebują sortowania.

srini.venigalla
źródło
5

ANSI SQL zezwala tylko ORDER BYna najbardziej zewnętrzne zapytanie z różnych powodów, z których jeden dzieje się, gdy podselekcja / widok / CTE jest dołączony do innej tabeli, a zapytanie zewnętrzne ma swoje ORDER BY.

Serwer SQL nigdy nie obsługiwał go w widoku (chyba że oszukałeś go za pomocą takiego, TOP 100 PERCENTktóry moim zdaniem w większości powoduje błąd).

Nawet jeśli wywołałeś błąd, wyniki nigdy nie były wiarygodne, a sortowanie nie zawsze przebiegało zgodnie z oczekiwaniami.

Zobacz ten post na blogu zespołu Optymalizatora zapytań, aby uzyskać pełne wyjaśnienie techniczne. TOP 100 procent ZAMÓWIENIE ZA Uznane za szkodliwe.

Domyślna implementacja planu dla tego kodu powoduje sortowanie wierszy w ramach wykonywania operacji TOP. Często oznaczało to, że wyniki były zwracane w posortowanej kolejności, co prowadziło klientów do przekonania, że ​​istnieje gwarancja sortowania wierszy. W rzeczywistości tak nie jest. Jeśli chcesz, aby wiersze były zwracane do użytkownika w posortowanej kolejności, musisz użyć ORDER BY w najbardziej zewnętrznym bloku zapytania (według ANSI), aby zagwarantować wyjściową kolejność prezentacji.

Tom V.
źródło
3

Widoki zachowują się jak tabele, których zawartość jest określona przez wyniki zapytania.

Tabele nie mają porządku; to tylko worki rzędów.

Dlatego widoki nie mają również porządku. Możesz je jednak sortować, wybierając wiersze w konkretnym ZAMÓWIENIU.

duskwuff
źródło
1
Tabele ... to tylko worki rzędów - a viwes to po prostu wirtualne worki wirtualnych rzędów - widoki „nie istnieją” - np. W ogóle nie są dla nich przechowywane żadne dane - to tylko „zapisane definicje zapytania do być wykonanym ”.
marc_s
1
+1 Równość tabel i widoków wydaje mi się głównym powodem, dla którego widoki nie powinny zawierać „zamówienia przez”
cud 173
1
„Widoki zachowują się jak tabele” . Powiedziałbym, że „Widoki zachowują się jak tabele podstawowe. Widoki to tabele”.
ypercubeᵀᴹ
-2

Jedną z jeszcze nie podanych odpowiedzi jest to, że „kolejność według” może zakłócać przepychanie predykatów, co może znacznie wpłynąć na wydajność.

Przykładem jest widok, w którym duży zestaw danych jest zestawiany w 10-liniowe podsumowanie, które znajduje się w pierwszej 10 / uporządkowane:

select * from TopOrderedView; -- Ordered 10 line summary in 5s

W tym samym przypadku z silnym predykatem:

select * from TopOrderedView where <condition>; -- Ordered 2 line summary in still 5s

Nadal zajmuje to tyle samo czasu, ponieważ polecenie top / order blokuje wcześniejsze uruchomienie predykatu w potoku. Może to powodować przetwarzanie niepotrzebnych wierszy, a plan będzie podobny do tego bez predykatu.

To, czy wypychanie powinno nastąpić przed złożeniem zamówienia, jest naprawdę wyborem programisty i może zmienić odpowiedź. Najczęściej push jest logiczną intencją.

Logiczne użycie „najwyższych 100 procent” pozwala na przepychanie predykatów, jednak implementacja niestety ignoruje w tym przypadku „kolejność do” i nie udaje się tego dokonać.

Dla prawdziwych przypadków użycia dobrym kompromisem może być wykonanie przez silnik „zamówienia przez pociągnięcie”. Umożliwiłoby to określenie „kolejności według” w widoku (z najwyższymi 100 procentami lub bez góry) i ta kolejność jest używana tylko wtedy, gdy widok jest wybierany bezpośrednio, bez wyraźnego zamówienia przez, bez złączeń, bez agregatów, nie przeglądanie łańcuchów itp. Oba wymienione powyżej przypadki mogą być obsługiwane przez ten prosty model.

Crokusek
źródło
-6

możesz utworzyć widok, który ma porządek według i zachowuje porządek, gdy zostanie zapytany po:

wybierz najlepsze 99,99999999999999 procent * od ..... uporządkuj według

NasF1
źródło
1
Dlaczego nie tylko SELECT TOP 100 PERCENT ...?
Max Vernon,
2
@Max prawdopodobnie podobny do tej sztuczki - nie jest to dobry pomysł.
Aaron Bertrand
Uzgodnione, @AaronBertrand - zauważając, że nie trzeba używać 99.9999999999999 :-)
Max Vernon