¿En qué momento se vuelve eficiente tener un índice?

9

He encontrado muchos recursos que mencionan que agregar un índice a una tabla hace que las búsquedas sean más rápidas y que las inserciones sean más lentas, pero solo si la tabla es grande. Esto crea una compensación, que es una decisión de diseño, pero debe haber un tamaño de tabla aproximado antes de que sea absurdo usar un índice. (10 filas, por ejemplo, probablemente estén muy por debajo de ese límite)

¿Alguien sabe dónde estaría este límite, o sabe de un recurso que me dirija en la dirección correcta?

SeanVDH
fuente
¿Cuál es la relación de lectura / escritura para su aplicación? Si realmente es intensivo en escritura, entonces tal vez sea el punto en el que debe tener en cuenta el compromiso de escritura, pero si es una aplicación habitual, agregaría el índice necesario en 99% de los casos (las tablas generalmente crecen, apenas volver en tamaño).
Marian

Respuestas:

12

El límite exacto es realmente difícil de determinar con anticipación.

Una cosa que la mayoría de las personas subestima son los altos requisitos que debe cumplir un índice, antes de convertirse en candidato para ser utilizado en una consulta.

Un índice eficiente (no agrupado)

  • ofrece una gran selectividad , por ejemplo, devuelve solo un porcentaje muy pequeño (<1%, <2%) del total de filas. Si la selectividad no es un dato, el optimizador de consultas de SQL Server probablemente ignorará este índice

  • idealmente debería cubrir la consulta, es decir, devolver todas las columnas requeridas por la consulta. Si puede crear un índice que tenga 1 o 2 columnas de índice, e incluya otras pocas (2-4) columnas como columnas incluidas y, por lo tanto, pueda cubrir una consulta, entonces es probable que el optimizador de consultas use este índice. Lo que también significa: si su código siempre se usa SELECT * .....para buscar todas las columnas , la probabilidad de que se utilicen índices disminuye, de manera bastante dramática, en realidad

Estoy seguro de que también hay muchos otros criterios, pero creo que estos dos son los más críticos. Por supuesto, siempre debe mantener sus índices debidamente mantenidos (reorganizar, reconstruir) y asegurarse de que las estadísticas asociadas con sus índices estén actualizadas.

PD: los índices no agrupados en columnas de clave externa son un caso especial; de manera predeterminada, siempre recomendaría agregarlos, ya que ayudan a acelerar tanto las comprobaciones de integridad referencial como JOINlas restricciones de FK. Pero incluso aquí, es absolutamente válido "extender" esos índices de columna FK agregando algunas columnas "incluir" adicionales para que sean aún más útiles.

marc_s
fuente
2
Si bien es posible que esta respuesta no responda directamente a la pregunta, lo hace mucho mejor al dar los principios de diseño importantes para el índice, y responde la pregunta que debería haber hecho en primer lugar.
SeanVDH
6

Es posible que vea una mejora de un índice con solo 10 filas.

En la siguiente prueba en mi máquina, la versión sin un índice se completó en 10.5segundos y la versión con un índice en 9.8segundos (consistente en 3 ejecuciones).

El índice en este caso solo consiste en 1 página de hoja, pero como la matriz de ranuras se ordena en orden de clave de índice, su presencia permite que SQL Server solo devuelva la única fila de interés en lugar de realizar una agregación en las 10.

CREATE TABLE T
(
X INT,
Y CHAR(100) NULL
)

INSERT INTO T (X)
SELECT number 
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 10

set nocount on;

DECLARE @I INT, @X INT

DECLARE @Time DATETIME2(7) = SYSUTCDATETIME()

SET @I = 1
    WHILE (@I < 1000000)
    BEGIN
    SELECT @X = MAX(X)
    FROM T
    SET @I += 1
    END

SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())

CREATE CLUSTERED INDEX IX ON T(X)
SET @Time = SYSUTCDATETIME()
SET @I = 1
    WHILE (@I < 1000000)
    BEGIN
    SELECT @X = MAX(X)
    FROM T
    SET @I += 1
    END

SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())

DROP TABLE T
Martin Smith
fuente
¿Los insertos se ven afectados de manera similar o la desaceleración es mínima?
SeanVDH
@SeanVDH: el ejemplo en mi respuesta es comparar un índice agrupado con un montón. Sería lógico pensar que las inserciones entre las filas existentes serían más lentas ya que las filas tienen que ir a un lugar específico y la matriz de ranuras reescrita también la posibilidad de divisiones de página. Para inserciones más grandes, los datos también pueden clasificarse en el orden de las claves de CI, lo cual es innecesario cuando se inserta en un montón. Kimberley Tripp argumenta aquí, sin embargo, que a veces insertar en un elemento de configuración puede ser mejor que insertar en un montón.
Martin Smith
Gracias por el artículo, ella presenta algunos puntos interesantes. Me preguntaba si las inserciones se verían afectadas tan dramáticamente como las selecciones en la tabla pequeña, pero tiene razón, la compensación debería ser similar al principio como lo sería más tarde.
SeanVDH