Índices do SQL Server - crescente ou decrescente, que diferença isso faz?


138

Ao criar um índice em uma coluna ou número de colunas no MS SQL Server (estou usando a versão 2005), você pode especificar que o índice em cada coluna seja crescente ou decrescente. Estou tendo dificuldade para entender por que essa escolha está aqui. Usando técnicas de classificação binária, uma pesquisa não seria tão rápida de qualquer maneira? Que diferença faz qual ordem eu escolho?


Respostas:


136

Isso é importante principalmente quando usado com índices compostos:

CREATE INDEX ix_index ON mytable (col1, col2 DESC);

pode ser usado para:

SELECT  *
FROM    mytable
ORDER BY
        col1, col2 DESC

ou:

SELECT  *
FROM    mytable
ORDER BY
        col1 DESC, col2

, mas não para:

SELECT  *
FROM    mytable
ORDER BY
        col1, col2

Um índice em uma única coluna pode ser usado com eficiência na classificação dos dois modos.

Veja o artigo no meu blog para obter detalhes:

Atualizar:

De fato, isso pode importar mesmo para um índice de coluna única, embora não seja tão óbvio.

Imagine um índice em uma coluna de uma tabela em cluster:

CREATE TABLE mytable (
       pk INT NOT NULL PRIMARY KEY,
       col1 INT NOT NULL
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)

O índice on col1mantém os valores ordenados col1junto com as referências às linhas.

Como a tabela está agrupada, as referências às linhas são, na verdade, os valores de pk. Eles também são ordenados dentro de cada valor de col1.

Isso significa que as folhas do índice são realmente ordenadas (col1, pk)e esta consulta:

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk

não precisa de classificação.

Se criarmos o índice da seguinte maneira:

CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC)

, os valores de col1serão classificados em ordem decrescente, mas os valores pkem cada valor de col1serão classificados em ordem crescente.

Isso significa que a seguinte consulta:

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk DESC

pode ser servido por, ix_mytable_col1_descmas não por ix_mytable_col1.

Em outras palavras, as colunas que constituem um CLUSTERED INDEXem qualquer tabela são sempre as colunas finais de qualquer outro índice nessa tabela.


1
Quando você diz "não para ...", você quer dizer que não vai funcionar ou o desempenho será horrível?
315 Neil N

5
Quero dizer que o índice não será usado para a consulta. A consulta em si funcionará, é claro, mas o desempenho será ruim.
Quassnoi 20/04/09

1
Na primeira seção, o segundo exemplo não deveria dizer "ORDER BY col1 DESC, col2 DESC"?
Mitch Wheat

71

Para um verdadeiro índice de coluna única, faz pouca diferença do ponto de vista do Query Optimizer.

Para a definição da tabela

CREATE TABLE T1( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] ASC))

A pergunta

SELECT TOP 10 *
FROM T1
ORDER BY ID DESC

Usa uma varredura ordenada com a direção da varredura, BACKWARDcomo pode ser visto no Plano de Execução. No entanto, há uma pequena diferença, pois atualmente apenas as FORWARDverificações podem ser paralelizadas.

Plano

No entanto , pode fazer uma grande diferença em termos de fragmentação lógica . Se o índice for criado com chaves descendentes, mas novas linhas forem anexadas com valores de chave ascendentes, você poderá terminar todas as páginas fora de ordem lógica. Isso pode afetar gravemente o tamanho das leituras de E / S ao verificar a tabela e ela não está no cache.

Veja os resultados da fragmentação

                    avg_fragmentation                    avg_fragment
name   page_count   _in_percent         fragment_count   _size_in_pages
------ ------------ ------------------- ---------------- ---------------
T1     1000         0.4                 5                200
T2     1000         99.9                1000             1

para o script abaixo

/*Uses T1 definition from above*/
SET NOCOUNT ON;

CREATE TABLE T2( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] DESC))

BEGIN TRAN

GO
INSERT INTO T1 DEFAULT VALUES
GO 1000
INSERT INTO T2 DEFAULT VALUES
GO 1000

COMMIT

SELECT object_name(object_id) AS name, 
       page_count, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM 
sys.dm_db_index_physical_stats(db_id(), object_id('T1'), 1, NULL, 'DETAILED') 
WHERE  index_level = 0 
UNION ALL 
SELECT object_name(object_id) AS name, 
       page_count, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM 
sys.dm_db_index_physical_stats(db_id(), object_id('T2'), 1, NULL, 'DETAILED') 
WHERE  index_level = 0 

É possível usar a guia de resultados espaciais para verificar a suposição de que isso ocorre porque as páginas posteriores têm valores-chave crescentes nos dois casos.

SELECT page_id,
       [ID],
       geometry::Point(page_id, [ID], 0).STBuffer(4)
FROM   T1
       CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
UNION ALL
SELECT page_id,
       [ID],
       geometry::Point(page_id, [ID], 0).STBuffer(4)
FROM   T2
       CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )

insira a descrição da imagem aqui


Obrigado Martin para este grande TIP, isso realmente me ajudou em consultas de classificação
TheGameiswar

Gostaria de saber se tenho um índice descendente e selecione minha coluna na minha tabela onde a coluna indexed = \ @myvalue é mais rápida quando \ @myvalue está mais próximo do valor máximo possível do que no caso em que \ @myvalue estiver fechado para o valor mínimo possível.
Lajos Arpad

@LajosArpad por que um seria mais rápido? Árvores B são árvores equilibradas. A profundidade da árvore é a mesma para ambos.
Martin Smith

@MartinSmith a profundidade é o mesmo, mas eu duvido que a ordem de irmãos não faria diferença
Lajos Arpad

@MartinSmith, se a ordem dos irmãos tiver uma pequena diferença no desempenho, a execução de milhões de seletores seria adicionada, sem mencionar as junções multidimensionais.
Lajos Arpad

8

A ordem de classificação é importante quando você deseja recuperar muitos dados classificados, não registros individuais.

Observe que (como você sugere na sua pergunta) a ordem de classificação é tipicamente muito menos significativa do que as colunas que você está indexando (o sistema pode ler o índice ao contrário, se a ordem for oposta ao que deseja). Raramente penso na ordem de classificação do índice, enquanto sofro com as colunas cobertas pelo índice.

@Quassnoi fornece um grande exemplo de quando isso não importa.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.