Por que ORDER BY não pertence a uma View?

51

I compreender que você não pode ter ORDER BY em uma exibição. (Pelo menos no SQL Server 2012, estou trabalhando com)

Também entendo que a maneira "correta" de classificar uma exibição é colocando uma declaração ORDER BYao redor da SELECTconsulta.

Mas, sendo relativamente novo no SQL prático e no uso de visualizações, gostaria de entender por que isso é feito por design. Se eu segui o histórico corretamente, isso já foi possível e foi explicitamente removido do SQL Server 2008 e assim por diante (não me cite na versão exata).

No entanto, o melhor motivo pelo qual a Microsoft removeu esse recurso é porque "uma exibição é uma coleção de dados não classificada".

Suponho que exista uma boa razão lógica para o motivo de uma Visualização não ser classificada. Por que uma visão não pode ser apenas uma coleção achatada de dados? Por que especificamente não classificado? Não parece difícil chegar a situações em que (pelo menos para mim / IMHO) parece perfeitamente intuitivo ter uma visão ordenada.

ngmiceli
fonte
2
A primeira resposta é perfeita. Eu sugeriria que se você deseja solicitar uma visão, por que não faz isso? Selecione [Colunas] em [YourView] Ordenar por [Colunas]
Zane
Resposta curta: "Pela mesma razão que ORDER BY não pertence a uma tabela".
ypercubeᵀᴹ

Respostas:

38

(Visões indexadas à parte, é claro.)

Uma visualização não é materializada - os dados não são armazenados; então, como eles podem ser classificados? Uma visualização é como um procedimento armazenado que contém apenas um SELECTsem parâmetros ... ele não contém dados, apenas a definição da consulta. Como referências diferentes à exibição podem precisar de dados classificados de maneiras diferentes, a maneira como você faz isso - assim como selecionar em uma tabela, que também é uma coleção não classificada de linhas, por definição - é incluir a ordem na consulta externa .

Também para dar uma pequena visão da história. Você nunca poderia colocar ORDER BYuma visão, sem incluir também TOP. E, neste caso, o ORDER BYditado por quais linhas foram incluídas TOP, não como elas seriam apresentadas. Aconteceu que no SQL Server 2000, se TOPera 100 PERCENTou {some number >= number of rows in the table}, o otimizador era bastante simplista e acabou produzindo um plano com uma classificação que correspondia à TOP/ORDER BY. Mas esse comportamento nunca foi garantido ou documentado - apenas se baseava na observação, o que é um mau hábito . Quando o SQL Server 2005 foi lançado, esse comportamento começou a "quebrar" devido a alterações no otimizador que levaram a diferentes planos e operadores sendo usados ​​- entre outras coisas, oTOP / ORDER BYseria completamente ignorado se fosse TOP 100 PERCENT. Alguns clientes reclamaram disso tão alto que a Microsoft emitiu um sinalizador de rastreamento para restabelecer o comportamento antigo. Não vou lhe dizer qual é o sinalizador porque não quero que você o use e quero ter certeza de que a intenção está correta - se você deseja uma ordem de classificação previsível, use ORDER BYna consulta externa.

Para resumir e esclarecer o que você fez: a Microsoft não removeu nada. Eles tornaram o produto melhor e, como efeito colateral, esse comportamento não documentado e não garantido se tornou menos confiável. No geral, acho que o produto é melhor para ele.

Aaron Bertrand
fonte
Aqui é mencionado (em um comentário) que o TOPexecuta uma operação de cursor sobre o conjunto de resultados. Por isso, pode ter uma ordem explícita.
21812 Tim Timmelelter
@ TimSchmelter que não ajuda quando o otimizador o vê TOP 100 PERCENT / ORDER BYe o remove completamente do plano. Experimente.
Aaron Bertrand
Foi apenas uma nota de rodapé. O restante do comentário é o seguinte: "o truque SELECT TOP x está programado para ser preterido em uma versão futura do SQL Server; portanto, é melhor não usá-lo".
Tim Schmelter
@ TimSchmelter já é um no-op. Eu não acho que ele irá parar de funcionar em qualquer nova versão em breve, porque quebrará muito código existente.
Aaron Bertrand
2
A ordem @ TimSchmelter não está falando sobre a ordem das linhas, mas sobre a ordem das colunas dentro de uma linha. No SQL Server, geralmente não falamos sobre uma linha ser uma tupla porque a implementação física de uma linha é muito óbvia para nós (a tabela lista as colunas na ordem em que você as definiu).
Aaron Bertrand
9

Se uma visualização foi autorizada a ser classificada, qual deve ser a ordem do resultado aqui?

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
fonte
Eu não entendo esse ponto. Em vez de escrever a exibição do banco de dados, você pode escrever uma consulta sql normal. Então, qual deve ser a ordem do resultado nesse caso? obrigado
hqt
7

uma possibilidade é evitar classificações conflitantes - se a visualização for classificada por um pedido e a seleção nessa visualização estiver classificada por outra ordem (sem estar ciente da classificação), poderá ocorrer um impacto no desempenho. Portanto, é mais seguro deixar o requisito de classificação para o usuário.

Por outro motivo, a classificação vem com um custo de desempenho. Por que penalizar todos os usuários da visualização, quando apenas alguns usuários precisam da classificação?

srini.venigalla
fonte
5

O ANSI SQL permite apenas a ORDER BYconsulta externa por uma variedade de razões, sendo uma delas o que acontece quando uma subseleção / view / CTE é associada a outra tabela e a consulta externa possui uma ORDER BYprópria.

O servidor SQL nunca o suportava em uma exibição (a menos que você o enganasse usando um TOP 100 PERCENTque, na minha opinião, está principalmente provocando um bug).

Mesmo que você tenha acionado o bug, os resultados nunca foram confiáveis ​​e a classificação nem sempre foi da maneira esperada.

Consulte esta postagem no blog da equipe do Query Optimizer para obter uma explicação técnica completa. TOP 100% ORDEM POR CONSIDERADO PREJUDICIAL.

A implementação do plano padrão para esse código classifica as linhas como parte da execução da operação TOP. Freqüentemente, isso significava que os resultados eram retornados na ordem de classificação e isso levava os clientes a acreditar que havia uma garantia de que as linhas foram classificadas. Este não é realmente o caso. Se você deseja que as linhas sejam retornadas ao usuário em ordem classificada, é necessário usar um ORDER BY no bloco de consulta mais externo (por ANSI) para garantir a ordem de apresentação da saída.

Tom V
fonte
3

As visualizações se comportam como tabelas cujo conteúdo é determinado pelos resultados de uma consulta.

As mesas não têm ordem; são apenas sacos de linhas.

Portanto, as visualizações também não têm ordem. Você pode classificá-los selecionando linhas em uma ORDER específica, no entanto.

crepúsculo
fonte
11
Tabelas ... são sacos apenas de linhas - e depois viwes são apenas virtuais sacos de virtuais filas - vistas "não existe" - por exemplo, não há dados armazenados para eles em tudo - eles são apenas "definições armazenados de uma consulta para ser executado ", basicamente.
marc_s 24/07
11
+1 A equivalência das tabels e pontos de vista me parece a principal razão pela qual pontos de vista não deve conter uma "order by"
miracle173
11
"As vistas se comportam como tabelas" . Eu diria que "as visualizações se comportam como tabelas de base. As visualizações são tabelas".
ypercubeᵀᴹ
-2

Uma resposta ainda não dada é que "ordenar por" pode interferir no envio de predicados, o que pode afetar muito o desempenho.

Um exemplo é ter uma exibição que agrupa um grande conjunto de dados em um resumo de 10 linhas que é o top 10 / Ordenado:

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

Para o mesmo caso com um predicado forte:

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

Ainda leva a mesma quantidade de tempo, porque a ordem de cima está impedindo que o predicado seja executado mais cedo no pipeline. Isso pode fazer com que as linhas desnecessárias sejam processadas e o plano será semelhante ao sem predicado.

Se o envio deve ocorrer antes do pedido é realmente uma escolha do desenvolvedor e pode alterar a resposta. Na maioria das vezes, o impulso é a intenção lógica.

O uso dos "100% principais" permite logicamente o envio de predicados, no entanto, infelizmente, a implementação ignora a ordem de "nesse caso" e derrota a intenção.

Para casos de uso reais, um bom compromisso seria o mecanismo executar "ordem puxando". Isso permitiria que um "pedido por" fosse especificado na exibição (com 100% ou mais top) e essa ordem será usada apenas se a exibição for selecionada diretamente, sem uma ordem explícita de, sem junções, sem agregados, sem ambos os casos listados acima podem ser suportados por este modelo simples.

crokusek
fonte
-6

você pode criar uma exibição que tenha ordem e preserve a ordem quando consultada após:

selecione os principais 99,999999999999 por cento * de ..... ordenar por

NasF1
fonte
11
Por que não apenas SELECT TOP 100 PERCENT ...?
Max Vernon
2
@ Max provavelmente semelhante a este truque - isso não faz uma boa ideia.
Aaron Bertrand
Acordado, @AaronBertrand - basta notar que não há necessidade de usar 99,99999999999 :-)
Max Vernon