Quando executo o código a seguir, leva 22,5 minutos e faz 106 milhões de leituras. No entanto, se eu executar apenas a instrução de seleção interna por si só, leva apenas 15 segundos e faz 264k leituras. Como uma observação lateral, a consulta de seleção não retorna registros.
Alguma idéia de por IF EXISTS
que isso faria com que ela durasse muito mais tempo e fizesse mais leituras? Também mudei a instrução select para fazer SELECT TOP 1 [dlc].[id]
e a matei após 2 minutos.
Como uma correção temporária, eu a alterei para fazer uma contagem (*) e atribuir esse valor a uma variável @cnt
. Então faz uma IF 0 <> @cnt
declaração. Mas eu pensei EXISTS
que seria melhor, porque se houvesse registros retornados na instrução select, ele pararia de executar a verificação / procura uma vez que encontrasse pelo menos um registro, enquanto o count(*)
procedimento concluirá a consulta completa. o que estou perdendo?
IF EXISTS
(SELECT [dlc].[ID]
FROM TableDLC [dlc]
JOIN TableD [d]
ON [d].[ID] = [dlc].[ID]
JOIN TableC [c]
ON [c].[ID] = [d].[ID2]
WHERE [c].[Name] <> [dlc].[Name])
BEGIN
<do something>
END
fonte
IF NOT EXISTS (...) BEGIN END ELSE BEGIN <do something> END
.Respostas:
Como expliquei na minha resposta a esta pergunta relacionada:
Como (e por que) o TOP afeta um plano de execução?
Usando
EXISTS
apresenta uma meta de linha, na qual o otimizador produz um plano de execução destinado a localizar a primeira linha rapidamente. Ao fazer isso, assume que os dados são distribuídos uniformemente. Por exemplo, se as estatísticas mostrarem 100 correspondências esperadas em 100.000 linhas, ele assumirá que precisará ler apenas 1.000 linhas para encontrar a primeira correspondência.Isso resultará em tempos de execução mais longos do que o esperado, se essa suposição estiver com defeito. Por exemplo, se o SQL Server escolher um método de acesso (por exemplo, verificação não ordenada) que localizar o primeiro valor correspondente muito tarde na pesquisa, isso poderá resultar em uma verificação quase completa. Por outro lado, se uma linha correspondente for encontrada entre as primeiras, o desempenho será muito bom. Esse é o risco fundamental das metas de linha - desempenho inconsistente.
Geralmente, é possível reformular a consulta para que uma meta de linha não seja atribuída. Sem o objetivo da linha, a consulta ainda pode terminar quando a primeira linha correspondente for encontrada (se gravada corretamente), mas a estratégia do plano de execução provavelmente será diferente (e, esperançosamente, mais eficaz). Obviamente, count (*) exigirá a leitura de todas as linhas, portanto, não é uma alternativa perfeita.
Se você estiver executando o SQL Server 2008 R2 ou posterior, geralmente também poderá usar o sinalizador de rastreamento documentado e suportado 4138 para obter um plano de execução sem uma meta de linha. Esse sinalizador também pode ser especificado usando a dica suportada
OPTION (QUERYTRACEON 4138)
, embora esteja ciente de que requer permissão sysadmin de tempo de execução , a menos que seja usado com um guia de plano.Infelizmente
Nenhuma das opções acima é funcional com uma
IF EXISTS
declaração condicional. Aplica-se apenas ao DML regular. Ele vai trabalhar com o suplenteSELECT TOP (1)
formulação você tentou. Isso pode ser melhor do que usarCOUNT(*)
, que precisa contar todas as linhas qualificadas, como mencionado anteriormente.Dito isso, existem várias maneiras de expressar esse requisito que permitirão evitar ou controlar a meta da linha, ao encerrar a pesquisa antecipadamente. Um último exemplo:
fonte
Como EXISTS só precisa encontrar uma única linha, ele usará uma meta de linha de uma. Às vezes, isso pode produzir um plano abaixo do ideal. Se você espera que seja assim, preencha uma variável com o resultado de um
COUNT(*)
e teste-a para ver se é maior que 0.Portanto ... Com um objetivo de linha pequena, evitará operações de bloqueio, como a criação de tabelas de hash ou a classificação de fluxos que podem ser úteis para unir junções, porque isso significa que ele deve encontrar algo rapidamente e, portanto, loops aninhados Seria melhor se encontrasse algo. Só que isso pode fazer um plano muito pior em todo o conjunto. Se encontrar uma única linha fosse rápida, você gostaria desse método para evitar bloqueios ...
fonte