2009-04-16 18 views
16

Si sé que un índice tendrá valores únicos, ¿cómo afectará el rendimiento en los insertos o si lo declaro como tal?Declarar un índice como único en SQL Server

Si el optimizador sabe que el índice es único, ¿cómo afectará eso al plan de consulta?

Entiendo que la especificación de uniquenes puede servir para preservar la integridad, pero dejando de lado esa discusión por el momento, ¿cuáles son las consecuencias del rendimiento?

+0

Integridad en su base de datos es casi siempre de suma importancia. –

Respuesta

23

Resumen breve: si sus datos son intrínsecamente UNIQUE, se beneficiará al crear un índice UNIQIE en ellos.

Ver el artículo en mi blog para obtener una explicación detallada:


Ahora, los detalles morbosos.

Como @Mehrdad dijo que, UNIQUENESS afecta el recuento de filas estimado en el generador de planes.

UNIQUE índice tiene una selectividad máxima posible, por eso:

SELECT * 
FROM table1 t2, table2 t2 
WHERE t1.id = :myid 
     AND t2.unique_indexed_field = t1.value 

casi seguramente utilizar NESTED LOOPS, mientras

SELECT * 
FROM table1 t2, table2 t2 
WHERE t1.id = :myid 
     AND t2.non_unique_indexed_field = t1.value 

pueden beneficiarse de un HASH JOIN si el optimizador piensa que non_unique_indexed_field no es selectiva.

Si el índice es CLUSTERED (i. E. Las filas theirselves están contenidos en las hojas de índice) y no UNIQUE, a continuación, una columna oculta especial llamada se añade uniquifier a cada clave de índice, con lo que la clave mayor y el índice más lento.

Es por eso que el índice UNIQUE CLUSTERED es de hecho un poco más eficiente que un non-UNIQUE CLUSTERED.

En Oracle, una combinación en UNIQUE INDEX se requiere para una tal llamada key preservation, que asegura que cada fila de una tabla se seleccionará como máximo una vez y hace una vista actualizable.

Esta consulta:

UPDATE (
     SELECT * 
     FROM mytable t1, mytable t2 
     WHERE t2.reference = t1.unique_indexed_field 
     ) 
SET  value = other_value 

trabajarán en Oracle, mientras éste:

UPDATE (
     SELECT * 
     FROM mytable t1, mytable t2 
     WHERE t2.reference = t1.non_unique_indexed_field 
     ) 
SET  value = other_value 

se producirá un error.

Esto no es un problema con SQL Server, sin embargo.

Una cosa más: de una tabla como ésta,

CREATE TABLE t_indexer (id INT NOT NULL PRIMARY KEY, uval INT NOT NULL, ival INT NOT NULL) 
CREATE UNIQUE INDEX ux_indexer_ux ON t_indexer (uval) 
CREATE INDEX ix_indexer_ux ON t_indexer (ival) 

, esta consulta:

/* Sorts on the non-unique index first */ 
SELECT TOP 1 * 
FROM t_indexer 
ORDER BY 
     ival, uval 

utilizará un TOP N SORT, mientras éste:

/* Sorts on the unique index first */ 
SELECT TOP 1 * 
FROM t_indexer 
ORDER BY 
     uval, ival 

usará solo un escaneo de índice.

Para la última consulta, no hay ningún punto en la ordenación adicional en ival, ya que uval son únicos de todos modos, y el optimizador tiene esto en cuenta.

En los datos de muestra de 200,000 filas (id == uval == ival), la consulta anterior se ejecuta durante 15 segundos, mientras que la última es instantánea.

+0

¿Hay una diferencia significativa entre uniones hash y uniones de bucle anidado? No está claro si estás sugiriendo que la distinción justifica una u otra. –

+1

Para la consulta anterior, los HASH JOIN son más eficientes en índices no selectivos, NESTED LOOP son más eficientes en los selectivos. El índice ÚNICO es el índice más selectivo, y el optimizador tendrá en cuenta la singularidad del índice al estimar la selectividad y elegir el algoritmo de combinación. – Quassnoi

+0

¿Está diciendo que no hay una respuesta general (depende en gran medida de la consulta)? ¿No hay una respuesta fácil para esto ?: si el índice * podría * ser único, ¿debería hacerlo único o no? –

4

Por supuesto, el optimizador tendrá en cuenta la singularidad. Afecta el recuento de filas esperado en los planes de consulta.

0

Sí, el motor de consultas lo tendrá en cuenta.

0

Quizás más importante: la exclusividad protegerá la integridad de los datos. El rendimiento sería una razón para ignorar esto.

rendimiento podría verse afectado positiva o negativamente o no del todo: lo haría depende de la consulta, si se utiliza el índice de rendimiento, etc

1

se ve afectado negativamente cuando la inserción de datos. Necesita verificar la singularidad.

+2

Y afectado positivamente al seleccionar datos: el optimizador puede explotar la singularidad. – kquinn

+6

No hay diferencia de rendimiento entre insertar un campo en un índice ÚNICO y no ÚNICO. El motor debería analizar el B-tree de todos modos, la singularidad solo afecta la decisión de insertar este valor en un lugar dado en el árbol B o no. – Quassnoi

+1

Tengo mucha curiosidad acerca de esto también.Los puntos de referencia o fuentes creíbles serían muy apreciados. –

1

Acabo de probar esto en mi máquina para una tabla de producción que contiene más de 1 millón de filas porque pensé que era una buena prueba. Los resultados fueron interesantes, aquí están los números en bruto:

- no Index:

Setup Time: 8888, Insert Time: 501690 

- restricción única:

Setup Time: 42, Insert Time: 488030 

El programa de instalación consistía en conseguir el máximo del campo que yo estaba agregando la Restricción única a, por lo que lógicamente el rendimiento se incrementó dramáticamente al agregar la restricción. Esto también mejoraría el rendimiento al buscar por esta clave externa.

Curiosamente, el tiempo de inserción mejoró ligeramente también (en un 2,7228%), por lo que solo los impactos positivos [en mi caso de prueba] de agregar la restricción (+ índice inherente).

Las pruebas solo muestran impactos positivos al agregar la restricción, sin impacto en el rendimiento.

NOTA: Para nuestro sistema de prueba, espero que los valores casi siempre sean únicos, así que no probé la inserción de valores no únicos, en esta información es una excepción, y no es algo que necesitemos realizar.

Cuestiones relacionadas