As varreduras constantes produzem uma única linha na memória sem colunas. O escalar de computação superior gera uma única linha com 3 colunas
Expr1005 Expr1006 Expr1004
----------- ----------- -----------
NULL NULL 60
O escalar de computação inferior gera uma única linha com 3 colunas
Expr1008 Expr1009 Expr1007
----------- ----------- -----------
NULL 1048576 10
O operador de concatenação Une essas 2 linhas e gera as 3 colunas, mas agora elas são renomeadas
Expr1010 Expr1011 Expr1012
----------- ----------- -----------
NULL NULL 60
NULL 1048576 10
A Expr1012
coluna é um conjunto de sinalizadores usados internamente para definir determinadas propriedades de pesquisa para o Mecanismo de Armazenamento .
O próximo escalar de computação ao longo de duas linhas de saída
Expr1010 Expr1011 Expr1012 Expr1013 Expr1014 Expr1015
----------- ----------- ----------- ----------- ----------- -----------
NULL NULL 60 True 4 16
NULL 1048576 10 False 0 0
As últimas três colunas são definidas da seguinte forma e são usadas apenas para fins de classificação antes de serem apresentadas ao Operador de Intervalo de Mesclagem
[Expr1013] = Scalar Operator(((4)&[Expr1012]) = (4) AND NULL = [Expr1010]),
[Expr1014] = Scalar Operator((4)&[Expr1012]),
[Expr1015] = Scalar Operator((16)&[Expr1012])
Expr1014
e Expr1015
apenas teste se certos bits estão ativados na bandeira.
Expr1013
parece retornar uma coluna booleana true se o bit for 4
estiver ativado e Expr1010
is NULL
.
Ao tentar outros operadores de comparação na consulta, obtenho esses resultados
+----------+----------+----------+-------------+----+----+---+---+---+---+
| Operator | Expr1010 | Expr1011 | Flags (Dec) | Flags (Bin) |
| | | | | 32 | 16 | 8 | 4 | 2 | 1 |
+----------+----------+----------+-------------+----+----+---+---+---+---+
| > | 1048576 | NULL | 6 | 0 | 0 | 0 | 1 | 1 | 0 |
| >= | 1048576 | NULL | 22 | 0 | 1 | 0 | 1 | 1 | 0 |
| <= | NULL | 1048576 | 42 | 1 | 0 | 1 | 0 | 1 | 0 |
| < | NULL | 1048576 | 10 | 0 | 0 | 1 | 0 | 1 | 0 |
| = | 1048576 | 1048576 | 62 | 1 | 1 | 1 | 1 | 1 | 0 |
| IS NULL | NULL | NULL | 60 | 1 | 1 | 1 | 1 | 0 | 0 |
+----------+----------+----------+-------------+----+----+---+---+---+---+
Pelo qual deduzo que o Bit 4 significa "Tem início do intervalo" (em vez de não ter limites) e o Bit 16 significa que o início do intervalo é inclusivo.
Este conjunto de resultados de 6 colunas é emitido pelo SORT
operador classificado por
Expr1013 DESC, Expr1014 ASC, Expr1010 ASC, Expr1015 DESC
. Assumir que True
é representado por 1
e False
pelo 0
conjunto de resultados representado anteriormente já está nessa ordem.
Com base em minhas suposições anteriores, o efeito líquido desse tipo é apresentar os intervalos no intervalo de mesclagem na seguinte ordem
ORDER BY
HasStartOfRangeAndItIsNullFirst,
HasUnboundedStartOfRangeFirst,
StartOfRange,
StartOfRangeIsInclusiveFirst
O operador de intervalo de mesclagem gera 2 linhas
Expr1010 Expr1011 Expr1012
----------- ----------- -----------
NULL NULL 60
NULL 1048576 10
Para cada linha emitida, é realizada uma busca por intervalo
Seek Keys[1]: Start:[dbo].[t].c2 > Scalar Operator([Expr1010]),
End: [dbo].[t].c2 < Scalar Operator([Expr1011])
Portanto, parece que duas buscas são realizadas. Um aparentemente > NULL AND < NULL
e um > NULL AND < 1048576
. No entanto, os sinalizadores passados parecem modificar isso para IS NULL
e < 1048576
respectivamente. Espero que o @sqlkiwi possa esclarecer isso e corrigir quaisquer imprecisões!
Se você alterar a consulta ligeiramente para
select *
from t
where
c2 > 1048576
or c2 = 0
;
Em seguida, o plano parece muito mais simples com uma pesquisa de índice com vários predicados de pesquisa.
O plano mostra Seek Keys
Start: c2 >= 0, End: c2 <= 0,
Start: c2 > 1048576
A explicação do motivo pelo qual esse plano mais simples não pode ser usado para o caso no OP é fornecida pelo SQLKiwi nos comentários da postagem do blog vinculada anteriormente .
Uma busca de índice com vários predicados não pode misturar diferentes tipos de predicados de comparação (por exemplo, Is
e Eq
no caso do OP). Essa é apenas uma limitação atual do produto (e é presumivelmente a razão pela qual o teste de igualdade na última consulta c2 = 0
é implementado usando >=
e <=
não apenas a igualdade direta que você procura para a consulta c2 = 0 OR c2 = 1048576
.
62
é para uma comparação de igualdade. Eu acho que60
deve significar que, em vez de> AND <
como mostrado no plano, você de fato recebe, a>= AND <=
menos que seja umaIS NULL
bandeira explícita, talvez (?) Ou talvez o bit2
indique outra coisa não relacionada e60
ainda seja a igualdade como quando eu façoset ansi_nulls off
e altero parac2 = null
ela, ainda permanece em60
As varreduras constantes são uma maneira de o SQL Server criar um bucket no qual colocará algo posteriormente no plano de execução. Eu postei uma explicação mais completa sobre isso aqui . Para entender para que serve a varredura constante, é necessário examinar mais detalhadamente o plano. Nesse caso, são os operadores de computação escalar que estão sendo usados para preencher o espaço criado pela varredura constante.
Os operadores de computação escalar estão sendo carregados com NULL e o valor 1045876; portanto, eles serão claramente usados com a junção de loop, em um esforço para filtrar os dados.
A parte realmente legal é que esse plano é trivial. Isso significa que passou por um processo mínimo de otimização. Todas as operações estão levando ao Intervalo de Mesclagem. Isso é usado para criar um conjunto mínimo de operadores de comparação para uma busca de índice ( detalhes sobre isso aqui ).
A idéia toda é livrar-se dos valores sobrepostos para poder extrair os dados com o mínimo de passes. Embora ainda esteja usando uma operação de loop, você notará que o loop é executado exatamente uma vez, ou seja, é efetivamente uma varredura.
ADENDO: Essa última frase está desativada. Houve duas buscas. Eu interpretei mal o plano. O restante dos conceitos é o mesmo e o objetivo, passes mínimos, é o mesmo.
fonte