2011-12-05 15 views
5

Hola, me preguntaba cuáles son los gastos generales de rendimiento para los índices de columna individual frente a los índices de varias columnas en términos de inserciones. Entonces, por ejemplo, si tengo 3 índices de columnas individuales, sería mejor para inserciones en esa tabla en lugar de tener 1 índice con múltiples columnas. Cuando estoy hablando de rendimiento, me interesa la velocidad bruta.Sobrecarga de rendimiento de una sola columna frente a varios índices de columna

Respuesta

4

La sobrecarga INSERT de INDEXes es normalmente despreciable independientemente de una o varias columnas.

A menos que escriba significativamente pesa lecturas, siempre incluya los índices necesarios para mejorar el rendimiento de sus consultas.

En algunos casos, varios índices de una sola columna aumentan el rendimiento de muchas más consultas que un solo índice de varias columnas. Más a menudo, un único índice de varias columnas aumenta aún más el rendimiento de un conjunto más pequeño de consultas.

La regla general es considerar el rendimiento de la consulta, no el rendimiento de la inserción, a menos que pueda predecir o ver un problema en particular con inserciones.

+4

He encontrado que la tara de inserción es significativa. ¿Qué base tiene para "normalmente insignificante"? – JNK

+0

@JNK: Excepto en casos excepcionales, las tablas se escriben con mucha menos frecuencia de la que se leen. Por órdenes de magnitud Además, cuando se escriben registros, la búsqueda para ubicarlos en un índice es una búsqueda simple, pero cuando se leen, las búsquedas son en su mayoría más complejas. Al hacer perfiles de capacidad, lo más común es ver lecturas significativamente enanas. Entonces, en términos relativos, la optimización de las escrituras a expensas de las lecturas es * generalmente * contraproducente. (Y en los escenarios donde ese no es el caso, el diseñador suele ser lo suficientemente experimentado como para no preguntar esto en SO.) – MatBailie

+0

@Dems parece que es bastante subjetivo para el sistema o más específicamente para una tabla en particular. – Kuberchaun

1

Creo que la única manera de responder es probar algunos escenarios en su hardware con los patrones de uso de su sistema. Típicamente, la sobrecarga del índice es enorme en comparación con no tener índices. De modo que cuantas más columnas haya en un índice, más gastos generales. Pero el impacto percibido por el usuario puede parecer nulo, pero perfila las diferentes pruebas y mira los números. He trabajado en lugares donde solo lanzan índices sobre todo. No estoy de acuerdo con este enfoque. Creo que deberías poner un índice sobre cuándo puedes probar que será de valor. Toman espacio además de agregar sobrecarga. De nuevo, necesitarás probar tu propia configuración para responder a tu pregunta.

+0

Estoy de acuerdo con el sentimiento de 'poner un índice sobre cuándo se puede probar que será de valor '. Mi respuesta simplemente expone la opinión de que el beneficio de un índice (que se está utilizando) raramente es menor que su costo. – MatBailie

+0

Estoy de acuerdo con eso. No es necesario que no uses índices porque crees que dañarán el rendimiento. En la mayoría de los casos, el beneficio del índice superará ampliamente el impacto en el desempeño de tener el índice. – Kuberchaun

0

Tenga en cuenta que un índice compuesto formado por 3 columnas como Apellido, Nombre y Ciudad no es útil cuando necesita buscar en Ciudad. Entonces, en este caso, necesitaría tener un índice solo para City.

1

si tengo 3 índices de una sola columna sería mejor para las inserciones en esa tabla en lugar de tener 1 índice con múltiples columnas.

Para las operaciones que modifican datos, un único índice con 3 columnas debe ser más rápido que 3 índices con una sola columna, por las razones siguientes:

  • Actualización de un índice requiere buscar a través de la B-Tree para la lugar correcto para realizar la modificación. Realizar búsqueda en un índice (incluso cuando es compuesto) tiende a ser más rápido que realizar 3 búsquedas en 3 índices.
  • Cada B-Tree leaf contiene una fila "puntero". 1 índice tendrá 3 veces menos punteros de fila que 3 índices (sin tener en cuenta los efectos de NULL, que normalmente no está indexado). Y, a menudo, los efectos secundarios del almacenamiento en caché son más pequeños.
  • 1 índice puede tienden a tener menos splitting y coalescencia de los nodos B-Tree en comparación con 3 índices.

Considere lo siguiente MS SQL Server de referencia:

CREATE TABLE ONE_INDEX (
    ID int PRIMARY KEY NONCLUSTERED, 
    F1 uniqueidentifier NOT NULL, 
    F2 uniqueidentifier NOT NULL, 
    F3 uniqueidentifier NOT NULL 
); 
CREATE INDEX ONE_INDEX_IE1 ON ONE_INDEX (F1, F2, F3); 

CREATE TABLE THREE_INDEXES (
    ID int PRIMARY KEY NONCLUSTERED, 
    F1 uniqueidentifier NOT NULL, 
    F2 uniqueidentifier NOT NULL, 
    F3 uniqueidentifier NOT NULL 
); 
CREATE INDEX THREE_INDEXES_IE1 ON THREE_INDEXES (F1); 
CREATE INDEX THREE_INDEXES_IE2 ON THREE_INDEXES (F2); 
CREATE INDEX THREE_INDEXES_IE3 ON THREE_INDEXES (F3); 
GO 



SET NOCOUNT ON 
DECLARE @t DATETIME; 
DECLARE @id INT; 
DECLARE @count INT; 
SET @count = 100000; 



PRINT 'ONE_INDEX:' 

SET @t = CURRENT_TIMESTAMP 
SET @id = 0; 
BEGIN TRANSACTION; 
WHILE @id < @count BEGIN 
    INSERT INTO ONE_INDEX VALUES(@id, NEWID(), NEWID(), NEWID()); 
    SET @id = @id + 1; 
END 
COMMIT TRANSACTION; 
PRINT ' INSERT ' + CAST(@count AS VARCHAR) + ' rows: ' + CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR) + ' ms'; 

SET @t = CURRENT_TIMESTAMP 
SET @id = 0; 
BEGIN TRANSACTION; 
WHILE @id < @count BEGIN 
    UPDATE ONE_INDEX SET F1 = NEWID(), F2 = NEWID(), F3 = NEWID() WHERE ID = @id 
    SET @id = @id + 1; 
END 
COMMIT TRANSACTION; 
PRINT ' UPDATE ' + CAST(@count AS VARCHAR) + ' rows: ' + CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR) + ' ms'; 

SET @t = CURRENT_TIMESTAMP 
DELETE FROM ONE_INDEX; 
PRINT ' DELETE ' + CAST(@count AS VARCHAR) + ' rows: ' + CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR) + ' ms'; 



PRINT 'THREE_INDEXES:' 

SET @t = CURRENT_TIMESTAMP 
SET @id = 0; 
BEGIN TRANSACTION; 
WHILE @id < @count BEGIN 
    INSERT INTO THREE_INDEXES VALUES(@id, NEWID(), NEWID(), NEWID()); 
    SET @id = @id + 1; 
END 
COMMIT TRANSACTION; 
PRINT ' INSERT ' + CAST(@count AS VARCHAR) + ' rows: ' + CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR) + ' ms'; 

SET @t = CURRENT_TIMESTAMP 
SET @id = 0; 
BEGIN TRANSACTION; 
WHILE @id < @count BEGIN 
    UPDATE THREE_INDEXES SET F1 = NEWID(), F2 = NEWID(), F3 = NEWID() WHERE ID = @id 
    SET @id = @id + 1; 
END 
COMMIT TRANSACTION; 
PRINT ' UPDATE ' + CAST(@count AS VARCHAR) + ' rows: ' + CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR) + ' ms'; 

SET @t = CURRENT_TIMESTAMP 
DELETE FROM THREE_INDEXES; 
PRINT ' DELETE ' + CAST(@count AS VARCHAR) + ' rows: ' + CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR) + ' ms'; 
GO 



DROP TABLE ONE_INDEX; 
DROP TABLE THREE_INDEXES; 
GO 

Qué (en mi MS SQL Server 2008 R2 debajo de la máquina virtual) impresiones:

ONE_INDEX: 
    INSERT 100000 rows: 4173 ms 
    UPDATE 100000 rows: 5530 ms 
    DELETE 100000 rows: 2706 ms 
THREE_INDEXES: 
    INSERT 100000 rows: 6640 ms 
    UPDATE 100000 rows: 10436 ms 
    DELETE 100000 rows: 3516 ms 

El aumento de la @count a 1.000.000 resultados en:

ONE_INDEX: 
    INSERT 1000000 rows: 40143 ms 
    UPDATE 1000000 rows: 55796 ms 
    DELETE 1000000 rows: 95576 ms 
THREE_INDEXES: 
    INSERT 1000000 rows: 61360 ms 
    UPDATE 1000000 rows: 91766 ms 
    DELETE 1000000 rows: 99500 ms 

Tenga en cuenta que en la mayoría de las cargas de trabajo las lecturas superan las escrituras, por lo que los esfuerzos de optimización suelen priorizar la cobertura de SELECT con índices a expensas de INSERT, UPDATE y DELETE. Además, un índice compuesto influirá en el rendimiento de la consulta de una manera diferente en comparación con 3 índices separados.

Solo usted puede realizar las pruebas adecuadas y alcanzar el equilibrio correcto entre todas estas preocupaciones.

Cuestiones relacionadas