2009-04-13 27 views
102

Cuando crea un índice en una columna o número de columnas en MS SQL Server (estoy usando la versión 2005), puede especificar que el índice en cada columna sea ascendente o descendente. Me cuesta entender por qué esta elección está aquí. Usando técnicas de clasificación binarias, ¿no sería una búsqueda igual de rápida en ambos sentidos? ¿Qué diferencia hace qué orden elijo?Índices de SQL Server: ascendente o descendente, ¿qué diferencia hace?

Respuesta

105

Esto es importante sobre todo cuando se utiliza con índices compuestos:

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

se puede utilizar para cualquiera de los dos:

SELECT * 
FROM mytable 
ORDER BY 
     col1, col2 DESC 

o:

SELECT * 
FROM mytable 
ORDER BY 
     col1 DESC, col2 

, pero no para:

SELECT * 
FROM mytable 
ORDER BY 
     col1, col2 

Un índice en una sola columna se puede usar de manera eficiente para ordenar en ambos sentidos.

Ver el artículo en mi blog para más detalles:

Actualización:

De hecho, esto se puede importar ni un solo índice de la columna, aunque no es tan obvio.

Imagínese un índice en una columna de una tabla agrupado:

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

El índice en col1 mantiene ordenada de col1 junto con las referencias a las filas.

Dado que la tabla está agrupada, las referencias a filas son en realidad los valores de pk. También se ordenan dentro de cada valor de col1.

Esto significa que eso deja de índice son realmente ordenada en (col1, pk), y esta consulta:

SELECT col1, pk 
FROM mytable 
ORDER BY 
     col1, pk 

necesidades sin clasificación.

si creamos el índice de la siguiente manera:

CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC) 

, descendente continuación se ordenarán los valores de col1, pero los valores de pk dentro de cada valor de col1 se ordenan ascendente.

Esto significa que la siguiente consulta:

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

puede ser servido por ix_mytable_col1_desc pero no por ix_mytable_col1.

En otras palabras, las columnas que constituyen un CLUSTERED INDEX en cualquier tabla son siempre las columnas finales de cualquier otro índice en esa tabla.

+0

Cuando dice "no para ..." Qué quiere decir no lo puedo trabajar o el rendimiento será horrible? –

+2

Quiero decir que el índice no se usará para la consulta. La consulta en sí funcionará, por supuesto, pero el rendimiento será pobre. – Quassnoi

+0

En la primera sección, ¿no debería el segundo ejemplo decir "PEDIDO POR col1 DESC, col2 DESC"? –

8

El orden de clasificación importa cuando desea recuperar muchos datos ordenados, no registros individuales.

Tenga en cuenta que (como sugiere con su pregunta) el orden de clasificación suele ser mucho menos significativo que las columnas que indexa (el sistema puede leer el índice en reversa si el orden es opuesto a lo que desea). Raramente le doy un orden de clasificación de índice a cualquier pensamiento, mientras que agonizo sobre las columnas cubiertas por el índice.

@Quassnoi proporciona un great example de cuando hace asunto.

53

Para un verdadero índice de columna individual, no hace mucha diferencia desde el punto de vista del Optimizador de consultas.

Para la definición de la tabla

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

La consulta

SELECT TOP 10 * 
FROM T1 
ORDER BY ID DESC 

Utiliza una exploración ordenada con el sentido de la exploración BACKWARD como puede verse en el plan de ejecución. Sin embargo, hay una ligera diferencia en que actualmente solo los escaneos FORWARD se pueden paralelizar.

Plan

Sin embargo se puede hacer una gran diferencia en términos de fragmentación lógica. Si el índice se crea con teclas que descienden, pero las nuevas filas se anexan con valores de clave ascendentes, puede terminar con cada página fuera de orden lógico. Esto puede afectar seriamente el tamaño de las lecturas de E/S al escanear la tabla y no está en la memoria caché.

ver resultados de la fragmentación

    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 el script de abajo

/*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 

Es posible usar la pestaña de resultados espaciales para verificar la suposición de que esto se debe a las páginas posteriores han ascendente valores clave en ambos 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 %%) 

enter image description here

+0

Gracias Martin por este gran TIP, esto realmente me ayudó en las consultas de rango – TheGameiswar

+0

Me pregunto si tengo un índice descendente, luego selecciono mycolumn de mytable donde indexed_column = \ @myvalue es más rápido cuando \ @myvalue está más cerca del valor máximo posible que en el caso cuando \ @myvalue está cerrado al valor mínimo posible. –

+0

@LajosArpad ¿por qué sería uno más rápido? B árboles son árboles equilibrados.La profundidad del árbol es la misma para ambos. –

Cuestiones relacionadas