Percebi que poucas pessoas entendem como os índices funcionam no SQL Server, especialmente as Colunas Incluídas. No entanto, os índices são a ótima maneira de otimizar as consultas. No início, também não tive a ideia das colunas incluídas, mas meus experimentos mostraram que elas são muito úteis.
Suponha que temos a seguinte tabela e consulta:
CREATE TABLE Person ( PersonID int, FirstName varchar(100), LastName varchar(100), Age int, … … ) SELECT FirstName, LastName, Age FROM Person WHERE FirstName = 'John' and LastName = 'Smith'
É claro que PersonID é uma chave primária. Suponha que tenhamos um índice pelo nome e sobrenome, vamos chamá-lo de IX_Person_FirstNameLastName. O plano de execução para tal consulta terá a seguinte aparência:
- Localizando todas as linhas com os nomes e sobrenomes especificados com a ajuda da árvore de índice IX_Person_FirstNameLastName
- Detectando a localização real da linha no disco nas folhas de índice, indo para a localização real e lendo a idade.
Agora, vamos considerar que essa consulta é executada com bastante frequência. Temos que executar 2 passos de cada vez. Pode ser otimizado? No caso do MS SQL Server, isso não é um problema – você pode incluir valores diretamente no índice com a ajuda da opção INCLUDE.
CREATE INDEX IX_PERSON ON Person ( FirstName, LastName ) INCLUDE(Age)
Agora, esse campo não é usado durante a indexação, mas é incluído no índice. Que problemas podemos enfrentar nesse sentido? Quando indexamos uma tabela por um determinado campo, o servidor de banco de dados deve construir uma árvore de índice por esse campo. Isso significa que precisamos alterar a árvore de índice ao alterar o valor. Quando os valores são modificados intensivamente, torna-se uma tarefa problemática e difícil para o servidor. Quando a atualização se torna muito grande, às vezes é mais fácil descartar o índice. O índice otimiza muito a pesquisa, mas afeta negativamente as operações de inserção, exclusão e atualização.
Se um campo é simplesmente incluído em um índice, ele não é usado durante a construção de uma árvore de índice e não a afeta, mas o valor pode ser facilmente encontrado na folha desta árvore. Quando uma pesquisa por sobrenome e nome ocorre, o servidor procura todos os nomes e sobrenomes da árvore e, quando atinge a folha (encontra o valor do índice necessário), além do ponteiro para o local físico dos valores de linha, ele também contém valores de campo incluídos no índice. Isso significa que não há necessidade de dar o segundo passo para mudar para o local físico da linha e lê-lo a partir daí.
Como você não precisa alterar a árvore ao modificar os dados de idade, tudo isso não afeta muito as operações de modificação de dados. Não precisamos alterar o índice, apenas precisamos alterar os valores na folha da árvore. É por isso que mesmo uma grande mudança no campo Idade não terá um grande impacto no desempenho. Certamente afetará, mas não tanto.
Até onde sei, os valores do índice clusterizado são incluídos automaticamente no nível folha, mas isso deve ser verificado com a especificação.
Então, quando o uso dos campos incluídos é benéfico? Quando são usados com frequência nos resultados da consulta, mas são alterados de vez em quando. Um exemplo é uma tabela de transações bancárias. Essa tabela pode ser composta pelos seguintes campos:número da conta, tipo de transação, data, soma. Não adianta indexar pela soma, mas podemos incluí-la no índice e isso agilizará significativamente a consulta.
Para recuperar o efeito real da indexação, as consultas não devem selecionar todos os campos, ou seja, devemos esquecer a tabela SELECT * FROM. Sempre recalcule apenas os campos que você realmente precisa. E se seus valores vierem a estar no índice, a velocidade de execução pode ser bastante alta.
Ferramenta útil:
dbForge Index Manager – suplemento SSMS útil para analisar o status de índices SQL e corrigir problemas com fragmentação de índice.