Versão curta: procurar é muito melhor
Versão menos curta: geralmente, a busca é muito melhor, mas muitas buscas (causadas por um design de consulta incorreto com subconsultas correlatas desagradáveis, por exemplo, ou porque você está fazendo muitas consultas em uma operação do cursor ou em outro loop) podem ser piores que um varredura, especialmente se sua consulta acabar retornando dados da maioria das linhas na tabela afetada.
Ajuda a cobrir toda a família para operações de localização de dados para entender completamente as implicações de desempenho.
Verificações de tabela: sem nenhum índice relevante para sua consulta, o planejador é forçado a usar uma verificação de tabela, o que significa que todas as linhas são examinadas. Isso pode resultar em todas as páginas relacionadas aos dados da tabela sendo lidas do disco, o que geralmente é o pior caso. Observe que, em algumas consultas, ele usará uma varredura de tabela mesmo quando um índice útil estiver presente - isso geralmente ocorre porque os dados na tabela são tão pequenos que é mais difícil percorrer os índices (se esse for o caso, você esperaria que o planeje mudar conforme os dados aumentem, supondo que a medida de seletividade do índice seja boa).
Varreduras de índice com pesquisas de linha: sem nenhum índice que possa ser usado diretamente para uma procura, mas um índice contendo as colunas da direita estiver presente, uma varredura de índice pode ser usada. Por exemplo, se você tiver uma tabela grande com 20 colunas com um índice na coluna1, col2, col3 e emitir SELECT col4 FROM exampletable WHERE col2=616
, nesse caso, a varredura do índice para consulta col2
é melhor do que a varredura da tabela inteira. Depois que as linhas correspondentes são encontradas, as páginas de dados precisam ser lidas para capturar col4 para saída (ou associação adicional), que é o estágio "pesquisa de marcador" quando você a vê nos planos de consulta.
Varreduras de índice sem pesquisas de linha: se o exemplo acima foi SELECT col1, col2, col3 FROM exampletable WHERE col2=616
necessário, não é necessário um esforço extra para ler as páginas de dados: depois que as linhas de índice correspondentes col2=616
forem encontradas, todos os dados solicitados serão conhecidos. É por isso que às vezes você vê colunas que nunca serão pesquisadas, mas provavelmente serão solicitadas para saída, adicionadas ao final dos índices - ele pode salvar pesquisas de linhas. Ao adicionar colunas a um índice por esse motivo e apenas por esse motivo, adicione-as com a INCLUDE
cláusula para informar ao mecanismo que ele não precisa otimizar o layout do índice para consultas com base nessas colunas (isso pode acelerar as atualizações feitas nessas colunas) . As varreduras de índice também podem resultar de consultas sem cláusulas de filtragem: SELECT col2 FROM exampletable
varrerá este exemplo de índice em vez das páginas da tabela.
Procura de índice (com ou sem pesquisas de linha) : em uma busca, nem todo o índice é considerado. Para a consulta, SELECT * FROM exampletable WHERE c1 BETWEEN 1234 AND 4567
o mecanismo de consulta pode encontrar a primeira linha que corresponderá fazendo uma pesquisa baseada em árvore no índice e, em c1
seguida, poderá navegar no índice em ordem até chegar ao final do intervalo (o mesmo ocorre com uma consulta pois, c1=1234
como pode haver muitas linhas correspondentes à condição, mesmo para uma =
operação). Isso significa que apenas as páginas de índice relevantes (mais algumas necessárias para a pesquisa inicial) precisam ser lidas em vez de todas as páginas do índice (ou tabela).
Índices em cluster : com um índice em cluster, os dados da tabela são armazenados nos nós folha desse índice, em vez de estarem em uma estrutura de heap separada. Isso significa que nunca será necessário fazer pesquisas adicionais de linha após localizar linhas usando esse índice, independentemente das colunas necessárias [a menos que você tenha dados fora da página, como TEXT
colunas ou VARCHAR(MAX)
colunas que contêm dados longos].
Você pode ter apenas um índice clusterizado por esse motivo [1] , o índice clusterizado é a sua tabela em vez de ter uma estrutura de heap separada; portanto, se você usar um [2], escolherá onde colocá-lo com cuidado para obter o máximo ganho.
Observe também que o índice em cluster porque a "chave de cluster" da tabela está incluída em todos os índices não em cluster da tabela; portanto, um índice em cluster amplo geralmente não é uma boa idéia.
[1] Na verdade, você pode efetivamente ter vários índices clusterizados definindo índices não clusterizados que cobrem ou incluem todas as colunas da tabela, mas é provável que seja um desperdício de espaço que tenha um impacto no desempenho de gravação, portanto, se você considerar fazer isso, verifique se você realmente precisa.
[2] Quando eu digo "se você usar um índice de cluster", note que é geralmente recomendado que você faça ter um em cada tabela. Há exceções, como em todas as regras práticas, as tabelas que veem pouco além de inserções em massa e leituras não ordenadas (tabelas de preparação para processos de ETL, talvez) sendo o exemplo de contador mais comum.
Ponto adicional: Varreduras incompletas:
É importante lembrar que, dependendo do restante da consulta, uma varredura de tabela / índice pode na verdade não varrer a tabela inteira - se a lógica permitir que o plano de consulta consiga fazer com que seja interrompido mais cedo. O exemplo mais simples disso é SELECT TOP(1) * FROM HugeTable
: se você olhar para o plano de consulta, verá que apenas uma linha foi retornada da varredura e se observar as estatísticas de E / S ( SET STATISTICS IO ON; SELECT TOP(1) * FROM HugeTable
), verá que ele lê apenas um número muito pequeno. de páginas (talvez apenas uma).
O mesmo pode acontecer se o predicado de uma cláusula WHERE
ou JOIN ... ON
puder ser executado simultaneamente com a varredura que é a origem e seus dados. Às vezes, o planejador / corredor de consulta pode ser muito inteligente ao enviar predicados de volta às fontes de dados para permitir o encerramento antecipado das verificações dessa maneira (e às vezes você pode reorganizar as consultas para ajudá-lo!). Enquanto os dados fluem da direita para a esquerda, conforme as setas na exibição do plano de consulta padrão, a lógica é executada da esquerda para a direita e cada etapa (da direita para a esquerda) não é necessariamente executada até a conclusão antes que a próxima possa começar. No exemplo simples acima, se você olhar para cada bloco no plano de consulta como um agente, o SELECT
agente solicita ao TOP
agente uma linha que, por sua vez, pede aoTABLE SCAN
agente para um, então o SELECT
agente pede para outro, mas o TOP
agente sabe que não há necessidade nem sequer pede ao leitor da mesa, o SELECT
agente recebe uma resposta "não é mais relevante" e sabe que todo o trabalho está feito. Muitas operações de bloquear este tipo de otimização é claro tantas vezes em exemplos mais complicados uma varredura na tabela / index realmente não ler cada linha, mas tome cuidado para não saltar para a conclusão de que qualquer verificação deve ser uma operação cara.