Perché ORDER BY non appartiene a una vista?


51

Io a capire che non si può avere ORDER BY in una visualizzazione. (Almeno in SQL Server 2012 con cui sto lavorando)

Comprendo anche che il modo "corretto" di ordinare una vista consiste nel mettere una dichiarazione ORDER BYattorno alla SELECTquery.

Ma essendo relativamente nuovo all'SQL pratico e agli usi delle viste, vorrei capire perché questo è fatto in base alla progettazione. Se ho seguito correttamente la cronologia, una volta era possibile ed è stato esplicitamente rimosso da SQL Server 2008 e così via (non citarmi sulla versione esatta).

Tuttavia, il miglior motivo per cui riesco a capire perché Microsoft ha rimosso questa funzionalità è perché "una vista è una raccolta di dati non ordinata".

Suppongo che ci sia una buona ragione logica per cui una vista dovrebbe essere ordinata. Perché una vista non può essere solo una raccolta di dati appiattita? Perché specificamente non ordinato? Non sembra così difficile trovare situazioni in cui (almeno per me / IMHO) sembra perfettamente intuitivo avere una vista ordinata.


2
La prima risposta è perfetta. Vorrei suggerire se desideri ordinare una vista perché non lo fai. Seleziona [Colonne] Da [YourView] Ordina per [Colonne]
Zane

Risposta breve: "Per lo stesso motivo per cui ORDER BY non appartiene a una tabella."
ypercubeᵀᴹ

Risposte:


38

(Viste indicizzate a parte, ovviamente.)

Una vista non si materializza: i dati non vengono archiviati, quindi come possono essere ordinati? Una vista è un po 'come una procedura memorizzata che contiene solo una SELECTsenza parametri ... non contiene dati, contiene solo la definizione della query. Poiché riferimenti diversi alla vista potrebbero richiedere dati ordinati in modi diversi, il modo in cui lo fai, proprio come la selezione da una tabella, che è anche una raccolta non ordinata di righe, per definizione - è di includere l'ordine nella query esterna .

Anche per dare un piccolo spaccato della storia. Non potresti mai mettere ORDER BYin vista, senza anche includerlo TOP. E in questo caso il ORDER BYdettato da quali file erano incluse TOP, non come sarebbero state presentate. È successo così che in SQL Server 2000, if TOPwas 100 PERCENTor {some number >= number of rows in the table}, l'ottimizzatore era abbastanza semplicistico e alla fine ha prodotto un piano con un tipo che corrispondeva a TOP/ORDER BY. Ma questo comportamento non è mai stato garantito o documentato - si basava solo sull'osservazione, che è una cattiva abitudine . Quando è uscito SQL Server 2005, questo comportamento ha iniziato a "rompersi" a causa dei cambiamenti nell'ottimizzatore che hanno portato all'utilizzo di piani e operatori diversi, tra cui ilTOP / ORDER BYsarebbe ignorato completamente se lo fosse TOP 100 PERCENT. Alcuni clienti si sono lamentati così tanto che Microsoft ha emesso un flag di traccia per ripristinare il vecchio comportamento. Non ti dirò quale sia la bandiera perché non voglio che tu la usi e voglio assicurarmi che l'intento sia corretto - se vuoi un ordinamento prevedibile, usa ORDER BYsulla query esterna.

Per riassumere e altrettanto per chiarire un punto che hai sottolineato: Microsoft non ha rimosso nulla. Hanno migliorato il prodotto e, come effetto collaterale, questo comportamento non documentato e non garantito è diventato meno affidabile. Nel complesso, penso che il prodotto sia migliore per questo.


Qui viene menzionato (in un commento) che TOPesegue un'operazione del cursore sul set di risultati. Pertanto può avere un ordine esplicito.
Tim Schmelter,

@TimSchmelter che non aiuta quando l'ottimizzatore lo vede TOP 100 PERCENT / ORDER BYe lo rimuove completamente dal piano. Provalo.
Aaron Bertrand

Era solo un sidenote. Il resto del commento è comunque il seguente: "il trucco SELECT TOP x è programmato per essere deprecato in una versione futura di SQL Server, quindi sarebbe meglio non usarlo affatto".
Tim Schmelter,

@TimSchmelter è già una no-op. Non credo che smetterà presto di funzionare in qualsiasi nuova versione, perché interromperà troppo il codice esistente.
Aaron Bertrand

2
@TimSchmelter ci ordine non parla l'ordine delle righe, si sta parlando l'ordine delle colonne all'interno di una riga. In SQL Server generalmente non parliamo di una riga che è una tupla perché l'implementazione fisica di una riga è così ovvia per noi (la tabella elenca le colonne nell'ordine in cui le hai definite).
Aaron Bertrand

9

Se è stato possibile ordinare una vista, quale dovrebbe essere l'ordine del risultato qui?

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 

Non capisco questo punto. Invece di scrivere la vista del database, è possibile scrivere una query sql normale. Quindi quale dovrebbe essere l'ordine del risultato in quel caso? grazie
hqt

7

una possibilità è quella di evitare ordinamenti in conflitto: se la vista viene ordinata in base a un ordine e la selezione in quella vista viene ordinata in base a un altro ordine (non essendo a conoscenza dell'ordinamento della vista), potrebbe esserci un impatto sulle prestazioni. Quindi è più sicuro lasciare all'utente il requisito di ordinamento.

un altro motivo, l'ordinamento ha un costo in termini di prestazioni, quindi perché penalizzare tutti gli utenti della vista, quando solo alcuni utenti hanno bisogno dell'ordinamento.


5

ANSI SQL consente la ORDER BYquery più esterna solo per una serie di motivi, uno dei quali è ciò che accade quando una sottoselezione / vista / CTE viene unita a un'altra tabella e la query esterna ha una ORDER BYstessa.

Il server SQL non l'ha mai supportato all'interno di una vista (a meno che tu non l'abbia ingannato usando una TOP 100 PERCENTche a mio avviso sta innescando un bug).

Anche se hai attivato il bug, i risultati non sono mai stati affidabili e l'ordinamento non è sempre uscito come previsto.

Vedi questo post sul blog da parte del team di Query Optimizer per una spiegazione tecnica completa. TOP 100 per cento ORDINA PER Considerato dannoso.

L'implementazione del piano predefinita per questo codice capita di ordinare le righe come parte dell'esecuzione dell'operazione TOP. Spesso ciò significava che i risultati venivano restituiti in ordine ordinato e ciò induceva i clienti a credere che esistesse la garanzia che le righe fossero ordinate. In realtà non è così. Se si desidera che le righe vengano restituite all'utente in ordine ordinato, è necessario utilizzare un ORDER BY sul blocco di query più esterno (per ANSI) per garantire l'ordine di presentazione dell'output.


3

Le viste si comportano come tabelle il cui contenuto è determinato dai risultati di una query.

Le tabelle non hanno ordine; sono solo sacchi di file.

Pertanto, anche le viste non hanno ordine. Tuttavia, puoi ordinarli selezionando le righe in un particolare ORDINE.


1
Tavoli ... sono solo sacchi di file - e poi viwes sono solo virtuali sacchi di virtual file - Visto "non esistono" - ad esempio, non ci sono dati memorizzati per loro a tutti - sono solo "definizioni memorizzati di una query a essere eseguito ", sostanzialmente.
marc_s

1
+1 L'equivalenza dei pannelli e delle viste mi sembra il motivo principale per cui le viste non dovrebbero contenere un "ordine per"
miracolo173

1
"Le viste si comportano come tabelle" . Direi che "Le viste si comportano come tabelle di base. Le viste sono tabelle".
ypercubeᵀᴹ

-2

Una risposta non ancora data è che "ordina per" può interferire con la spinta del predicato che può influire notevolmente sulle prestazioni.

Un esempio è avere una vista che raggruppa una grande serie di dati in un riepilogo di 10 righe tra i primi 10 / Ordinati:

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

Per lo stesso caso con un predicato forte:

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

Ci vuole ancora la stessa quantità di tempo perché il top / order by sta bloccando l'esecuzione del predicato in precedenza nella pipeline. Ciò può causare l'elaborazione di righe non necessarie e il piano sarà simile a quello senza predicato.

Se la spinta debba avvenire prima che l'ordine sia realmente una scelta dello sviluppatore e può cambiare la risposta. Molto spesso la spinta è l'intento logico.

L'uso logico del "top 100 percento" consente logicamente il push del predicato, ma l'implementazione sfortunatamente ignora "ordina per" per questo caso e vanifica l'intento.

Per casi d'uso reali, un buon compromesso sarebbe per il motore di eseguire "l'ordine tirando". Ciò consentirebbe di specificare un "ordine per" all'interno della vista (con il massimo del 100 percento o senza il massimo) e quell'ordine viene utilizzato solo se la vista viene selezionata direttamente, senza un ordine esplicito di, nessun join, nessun aggregato, no visualizzare il concatenamento, ecc. Entrambi i casi sopra elencati potrebbero essere supportati da questo semplice modello.


-6

puoi creare una vista che ha un ordine e conserva l'ordine entro quando viene richiesto:

seleziona la migliore 99.99999999999999 percento * da ..... ordina per


1
Perché non solo SELECT TOP 100 PERCENT ...?
Max Vernon,

2
@Max probabilmente è simile a questo trucco - questo non lo rende una buona idea.
Aaron Bertrand

D'accordo, @AaronBertrand - solo notando che non è necessario utilizzare 99.99999999999 :-)
Max Vernon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.