Estou escrevendo em uma publicação futura do meu blog sobre funções de janela agregadas e de classificação, especificamente os iteradores do Projeto de Segmento e Sequência. Pelo que entendi, o segmento identifica linhas em um fluxo que constitui o fim / início de um grupo, portanto, a seguinte consulta:
SELECT ROW_NUMBER() OVER (PARTITION BY someGroup ORDER BY someOrder)
Usará o segmento para saber quando uma linha pertence a um grupo diferente da linha anterior. O iterador do Sequence Project faz o cálculo do número da linha real, com base na saída da saída do iterador do segmento.
Mas a consulta a seguir, usando essa lógica, não deve incluir um segmento, porque não há expressão de partição.
SELECT ROW_NUMBER() OVER (ORDER BY someGroup, someOrder)
No entanto, quando tento essa hipótese, essas duas consultas usam um operador de segmento. A única diferença é que a segunda consulta não precisa de um GroupBy
no segmento. Isso não elimina a necessidade de um segmento em primeiro lugar?
Exemplo
CREATE TABLE dbo.someTable (
someGroup int NOT NULL,
someOrder int NOT NULL,
someValue numeric(8, 2) NOT NULL,
PRIMARY KEY CLUSTERED (someGroup, someOrder)
);
--- Query 1:
SELECT ROW_NUMBER() OVER (PARTITION BY someGroup ORDER BY someOrder)
FROM dbo.someTable;
--- Query 2:
SELECT ROW_NUMBER() OVER (ORDER BY someGroup, someOrder)
FROM dbo.someTable;
fonte
<GroupBy />
modo que o segmento realmente não faz nada, quase, produz a coluna do segmento para o operador Sequence Project. A razão para o operador do segmento estar lá pode ser que o operador do Projeto de Sequência precise desse valor para realizar seu trabalho.Respostas:
Encontrei este post de 6 anos mencionando o mesmo comportamento.
Parece que
ROW_NUMBER()
sempre inclui um operador de segmento,PARTITION BY
usado ou não. Se eu tivesse que adivinhar, diria que isso ocorre porque facilita a criação de um plano de consulta no mecanismo.Se o segmento é necessário na maioria dos casos, e nos casos em que não é necessário, é essencialmente uma não operação de custo zero, é muito mais simples incluí-lo sempre no plano quando uma função de janelas é usada.
fonte
De acordo com showplan.xsd para o plano de execução,
GroupBy
aparece semminOccurs
oumaxOccurs
atributos que, por conseguinte, são padronizados para [1..1] tornar o elemento obrigatório, não necessariamente conteúdo. O elemento filhoColumnReference
do tipo (ColumnReferenceType
) possuiminOccurs
0 emaxOccurs
ilimitado [0 .. *], tornando-o opcional , portanto, o elemento vazio permitido. Se você tentar remover manualmenteGroupBy
e forçar o plano, receberá o erro esperado:Curiosamente, descobri que você pode remover manualmente o operador Segment para obter um plano válido para forçar que se parece com isso:
No entanto, quando você executa esse plano (usando
OPTION ( USE PLAN ... )
), o Operador de segmento reaparece magicamente. Apenas mostra que o otimizador leva apenas os planos XML como um guia aproximado.Meu equipamento de teste:
Recorte o plano XML da plataforma de teste e salve-o como um .sqlplan para visualizar o plano menos o Segmento.
PS: Eu não gastaria muito tempo analisando os planos do SQL manualmente, como se você me conhecesse, saberia que considero isso um trabalho ocupado e demorado, e algo que eu nunca faria. Oh, espere !? :)
fonte