Operação física da concatenação: Garante a ordem de execução?

12

No SQL padrão, o resultado de a union allnão é garantido em nenhuma ordem. Então, algo como:

select 'A' as c union all select 'B'

Pode retornar duas linhas em qualquer ordem (embora, na prática, em qualquer banco de dados que eu conheça, 'A' venha antes de 'B').

No SQL Server, isso se transforma em um plano de execução usando uma operação física de "concatenação".

Eu poderia facilmente imaginar que a operação de concatenação varreria suas entradas, retornando qualquer entrada com registros disponíveis. No entanto, encontrei a seguinte declaração na web ( aqui ):

O Query Processor executará esse plano na ordem em que os operadores aparecerem no plano, o primeiro é o primeiro e o último é o final.

Pergunta: Isso é verdade na prática? Isso é garantido para ser verdade?

Não encontrei nenhuma referência na documentação da Microsoft de que as entradas sejam digitalizadas em ordem, do primeiro ao último. Por outro lado, sempre que tento executá-lo, os resultados sugerem que as entradas são, de fato, processadas em ordem.

Existe uma maneira de o mecanismo processar mais de uma entrada de cada vez? Meus testes (usando expressões muito mais complicadas do que constantes) estão em uma máquina de 8 núcleos ativada em paralelo, e a maioria das consultas tira proveito do paralelismo.

Gordon Linoff
fonte

Respostas:

10

Não , não há documentação da Microsoft que garanta o comportamento, portanto não é garantido .

Além disso, supondo que o artigo do Simple Talk esteja correto e que o operador físico de concatenação sempre processe as entradas na ordem mostrada no plano (muito provável que seja verdade), sem garantia de que o SQL Server sempre gerará planos que mantêm o mesmo a ordem entre o texto da consulta e o plano de consulta, você está apenas um pouco melhor.

Podemos investigar isso ainda mais. Se o otimizador de consulta conseguiu reordenar a entrada do operador Concatenação, deve haver linhas na DMV não documentada, sys.dm_exec_query_transformation_statscorrespondente a essa otimização.

SELECT * FROM sys.dm_exec_query_transformation_stats 
    WHERE name LIKE '%CON%' OR name LIKE '%UNIA%'

No SQL Server 2012 Enterprise Edition, isso produz 24 linhas. Ignorando as correspondências falsas para transformações relacionadas a constantes, há uma transformação relacionada ao Operador Físico de Concatenação UNIAtoCON(União Tudo à Concatenação). Portanto, no nível do operador físico, parece que uma vez selecionado o operador de concatenação, ele será processado na ordem do operador lógico da União Todos os quais foi derivado.


De fato, isso não é bem verdade. Existem reescrições pós-otimização que podem reordenar as entradas para um operador físico de concatenação após a conclusão da otimização baseada em custos. Um exemplo ocorre quando a concatenação está sujeita a uma meta de linha (portanto, pode ser importante ler primeiro a entrada mais barata). Consulte UNION ALLOtimização por Paul White para obter mais detalhes.

Essa reescrita física tardia foi funcional até e incluindo o SQL Server 2008 R2, mas uma regressão significou que não era mais aplicada ao SQL Server 2012 e posterior. Foi lançada uma correção que restabelece essa reescrita no SQL Server 2014 e posterior (não em 2012) com os hotfixes do otimizador de consulta habilitados (por exemplo, sinalizador de rastreamento 4199).


Mas sobre o operador Logical Union All ( UNIA)? Há uma UNIAReorderInputstransformação, que pode reordenar as entradas. Também há dois operadores físicos que podem ser usados ​​para implementar uma União lógica UNIAtoCONe , UNIAtoMERGE(União tudo para mesclar União).

Portanto, parece que o otimizador de consulta pode reordenar as entradas para a UNION ALL; no entanto, não parece ser uma transformação comum (nenhum uso de UNIAReorderInputsnos servidores SQL que tenho prontamente acessível. Não sabemos as circunstâncias que levariam o otimizador a usar UNIAReorderInputs; embora certamente seja usado quando um guia ou uso de um plano A dica de plano é usada para forçar um plano gerado usando as entradas reordenadas físicas da meta de linha mencionadas acima.

Existe uma maneira de o mecanismo processar mais de uma entrada de cada vez?

O operador físico de concatenação pode existir dentro de uma seção paralela de um plano. Com alguma dificuldade, consegui produzir um plano com concatenações paralelas usando a seguinte consulta:

SELECT userid, regdate  FROM (  --Users table is around 3mil rows
    SELECT  userid, RegDate FROM users WHERE userid > 1000000
    UNION 
    SELECT  userid, RegDate FROM users WHERE userid < 1000000
    UNION all
    SELECT userid, RegDate FROM users WHERE userid < 2000000
    ) d ORDER BY RegDate OPTION (RECOMPILE)

Portanto, no sentido mais estrito, o operador físico de concatenação parece sempre processar as entradas de maneira consistente (primeiro primeiro, segundo inferior); no entanto, o otimizador pode alternar a ordem das entradas antes de escolher o operador físico ou usar uma união de mesclagem em vez de uma concatenação.

StrayCatDBA
fonte
8

Segundo Craig Freedman, a ordem de execução do operador de concatenação é garantida.

Em sua postagem no blog Vendo planos de consulta em blogs do MSDN:

Observe que quando um operador tem mais de um filho, a ordem dos filhos é importante. O filho mais alto é o primeiro filho, enquanto o filho mais baixo é o segundo. O operador de concatenação processa os filhos nesta ordem.

E dos livros on-line Showplan Referência de Operadores Lógicos e Físicos

O operador físico de concatenação possui duas ou mais entradas e uma saída. A concatenação copia as linhas do primeiro fluxo de entrada para o fluxo de saída e repete esta operação para cada fluxo de entrada adicional.

Mikael Eriksson
fonte
Essa citação está bem próxima do que eu estava procurando. Estou disposto a dar o salto de ser executado nessa ordem para ser devolvido nessa ordem - embora seja decepcionante que a documentação impeça o processamento paralelo nesse caso.
Gordon Linoff 23/06
2

Resposta do wiki da comunidade :

Não sei se você pode provar que qualquer comportamento observado é sempre garantido, de um jeito ou de outro, a menos que você possa fabricar um contra-exemplo. Na ausência disso, a maneira de corrigir a ordem em que os resultados são retornados, é claro, é adicionar um ORDER BY.

Não sei se existe uma "correção" ou se existe uma necessidade de correção, se você puder demonstrar que em alguns cenários as consultas são processadas em uma ordem diferente.

A falta de documentação oficial explícita sugere para mim que você não deve depender disso. Esse é exatamente o tipo de coisa que causou problemas às pessoas ORDER BYem uma exibição, e GROUP BYsem ela ORDER BY, oito anos atrás, quando o otimizador do SQL Server 2005 foi lançado.

Com todos os novos recursos das versões mais recentes do SQL Server (com mais novidades), mesmo se você acha que pode garantir um comportamento específico hoje, eu não esperaria que isso fosse verdade (até que esteja documentado).

Mesmo que você não dependa desse comportamento, o que você fará com os resultados? De qualquer forma, eu não chamaria um artigo do Simple Talk por um funcionário externo . Pelo que sabemos, isso é apenas um palpite baseado em observação.

A Microsoft nunca publicará documentação oficial dizendo que 'x' não garante 'y'. Essa é uma das razões pelas quais ainda, quase uma década depois, temos dificuldade em convencer as pessoas de que elas não podem confiar nas ordens observadas ORDER BY- não há documentação que indique "isso não é garantido".

user126897
fonte