Eu tenho um problema estranho de compilação de consultas que é difícil de reproduzir. Isso acontece apenas com alta carga e não pode ser facilmente repetido.
- Existe uma tabela T com as colunas A, B, C, D.
- Há um índice clusterizado não exclusivo em T (A, B, C, D).
- Há uma consulta SELECT * FROM T ONDE A = @ P1 AND B = @ P2 AND (C = @ P3 OU C = @ P4) AND D = @ P5. A condição de busca está em todas as colunas do índice em cluster, a terceira coluna possui um OR.
O problema é que o plano de consulta dessa consulta possui o Predicado de busca apenas em A e B! O predicado em C e D é um predicado comum, portanto, isso significa que a árvore de pesquisa nas colunas C e D não é utilizada.
Os tipos de dados para todos os parâmetros correspondem aos tipos de dados da coluna.
Alguém poderia dar alguma dica de por que isso poderia estar acontecendo? A versão do SQL é 2008 R2 (SP1) - 10.50.2789.0 (X64)
OPTION (RECOMPILE)
?Respostas:
Para uma consulta parametrizada, ele não pode apenas fazer duas buscas em
e
Porque se
@P3 = @P4
isso traria incorretamente linhas duplicadas. Portanto, seria necessário um operador que removeu duplicatas delas primeiro.A partir de um teste rápido, esse aspecto parece depender do tamanho da tabela, independentemente de você ter ou não isso. No teste abaixo
245
/246
linhas é o ponto de corte entre os planos (esse também foi o ponto de corte entre o índice que cabe tudo em uma página e ele se torna 2 páginas de folha e uma página raiz).1 páginas / 245 linhas
Esse plano tem uma busca
A=1 AND B=2
com um predicado residual em(C=@C1 OR C=@C2) AND D=5
2 folhas Páginas / 246 linhas
No segundo plano, os operadores extras são responsáveis por remover quaisquer duplicatas do
@C1,@C2
primeiro antes de realizar as buscas.A busca no segundo plano é na verdade uma busca de intervalo entre
A=1 AND B=2 AND C > Expr1010
eA=1 AND B=2 AND C < Expr1011
com um predicado residual ativadoD=5
. Ainda não é uma busca de igualdade nas quatro colunas. Mais informações sobre os operadores de plano adicionais podem ser encontradas aqui .A adição
OPTION (RECOMPILE)
permite inspecionar os valores dos parâmetros em busca de duplicatas no tempo de compilação e produz um plano com duas buscas de igualdade.Você também pode conseguir isso com
Mas, na verdade, nesse caso de teste, seria contraproducente, pois duas buscas no índice de página única, em vez de uma, aumentam a IO lógica.
fonte
select .. union select ...
também daria a você duas buscas, além da etapa adicional de remover duplicatas do resultado.SELECT * FROM T WHERE A=1 AND B=2 AND C=@C1 AND D=5 UNION SELECT * FROM T WHERE A=1 AND B=2 AND C=@C2 AND D=5
pode remover incorretamente duplicatas que devem ser retornadas. No meu exemplo de dados onde eu preguiçosamente povoada todos com o mesmo valor que ele iria retornar 1 linha não256
Concordo totalmente com a análise de Martin. Esta consulta não pode produzir uma pesquisa nas quatro colunas devido ao predicado OU, a menos que (talvez) com OPTION (RECOMPILE). Suponho que essa seja uma consulta com agulha no palheiro, e provavelmente você não deseja uma sobrecarga extra.
Que tal agora:
Eu não testei isso, mas a outra parte deve fornecer 2 pesquisas em todos os 4 valores e uma união barata por meio de concatenação. No caso em que ambas as buscas acabem na mesma página, não acho que uma leitura lógica extra da página traga muito tempo. No entanto, dependendo dos seus dados, as duas buscas podem muito bem estar em páginas diferentes.
fonte