Entendo como uma única coluna indexada funciona no SQL Server e como ela é implementada usando árvores balanceadas. Há muitos vídeos interessantes no YouTube sobre esse assunto. No entanto, não entendo como funciona se o índice for baseado em várias colunas. Por exemplo:
CREATE NONCLUSTERED INDEX idxItemsCatState
ON Items (Category,OfferState)
INCLUDE ([Id],[Ranking])
E como isso pode acelerar consultas como
SELECT ID, Ranking FROM Items where Category = 1 AND OfferState < 3
Ainda é implementado como B-Tree? Como ele pode avaliar a combinação de valores? Quais são as restrições para tal recurso?
Para armazenar linhas em uma b-tree e realizar uma busca, tudo o que é necessário é uma ordem na qual as linhas devem ser classificadas. Assim como você pode classificar
(Category)
, você também pode classificar na tupla(Category, OfferState)
. No último caso, as linhas são primeiro classificadas porCategory
e, em seguida, quaisquer empates são desfeitos pela classificação porOfferState
.O índice resultante usará a mesma estrutura de árvore b, mas o valor para cada entrada na árvore b será uma
(Category, OfferState)
tupla.Para sua consulta, o SQL Server pode realizar uma busca da seguinte forma:
Category = 1
. Isso pode ser feito usando a mesma busca de árvore b com a qual você está familiarizado, com o SQL Server precisando usar apenas aCategory
parte de cada(Category, OfferState)
tupla.OfferState >= 3
encontrar uma linha comDessa forma, o SQL Server poderá buscar diretamente o início do intervalo de linhas necessárias, ler essas linhas e parar no final do intervalo de linhas. Observe que você pode ver como essa busca funciona observando a
Seek Predicate
propriedade doIndex Seek
operador em seu plano de consulta.De modo mais geral, um índice de várias colunas entre colunas
(a, b, c, d, ...)
pode oferecer suporte a uma busca em qualquer subconjunto de colunas à esquerda, como(a)
ou(a, b, c)
, quando você está fazendo a correspondência de igualdade (usando=
).Se você estiver procurando por um intervalo (por exemplo,
b < 3
), o SQL Server não poderá mais procurar em nenhuma coluna que caia posteriormente no índice. Nesse caso, seria necessário realizar uma busca separada dentro de cada valor distinto deb
, o que não é suportado (exceto em um caso mais específico com o qual você provavelmente não precisa se preocupar: entre partições de uma tabela particionada).Os índices tradicionais são implementados como árvores B, sejam chaves de uma ou várias colunas.
A ordem das chaves de índice composto é significativa para a otimização da consulta. Especifique a(s) coluna(s) usada(s) em predicados de igualdade primeiro (em ordem de seletividade), seguida(s) pela(s) coluna(s) usada(s) com predicados de desigualdade. Isso facilitará o toque apenas nas linhas que correspondem à condição de igualdade e, em seguida, acessará as linhas dentro do intervalo especificado. Portanto, para esta consulta, a ordem das colunas no índice deve ser Categoria e OfferState, e não vice-versa.
Logicamente, as colunas individuais são colocadas em uma tupla
(Category, OfferState)
. Essas tuplas são as chaves de índice e o algoritmo b-tree funciona sem modificações.As árvores B não precisam de nenhum tipo de "condição". Eles trabalham em qualquer domínio de valor que tenha uma ordem total definida. As únicas operações que estão sendo feitas no sentido da estrutura de dados é comparar duas chaves. Além disso, o SQL Server usa mais duas operações: serialização para bytes e desserialização de bytes.