2008-10-30 15 views
12

Obviamente (creo), crear un índice en una columna BIT es innecesario. Sin embargo, si tenía una columna que necesita buscar en la que cada valor es probablemente único, como BlogPost o StreetAddress o algo así, entonces un índice parece apropiado (de nuevo, creo).Cuándo crear un nuevo índice de SQL Server?

Pero, ¿cuál es el límite? ¿Qué sucede si espera 10.000 filas y tendrá alrededor de 20 valores únicos entre ellas? ¿Debería crearse un índice?

Gracias de antemano.

Respuesta

15

La mejor respuesta a esto es hacer un perfil de sus consultas y ver si el índice mejora sus consultas. La dificultad para responder esto es que es casi imposible generalizar el comportamiento del optimizador de consultas.

Dicho esto, una regla de oro es, si su selectividad es 10% o menos en una determinada consulta en una tabla, entonces es muy probable que se benefician de un índice. Por lo tanto, en su ejemplo, usted podría beneficiarse de un índice si sus valores se distribuyen de manera uniforme. Sin embargo, teniendo en cuenta que su tabla es pequeña, su impulso de rendimiento puede ser insignificante.

Esta no es una regla difícil ya que hay muchos factores que pueden cambiar el 10%, incluido el uso de un tipo agrupado u otro tipo de índice, el tamaño de las filas, si algunas columnas no están en línea, consulta estructura, etc.

también hay que tener en cuenta que hay una penalización de rendimiento significativo para la inserción en una tabla con un índice. Si esta tabla se actualiza o anexa con frecuencia, el aumento de velocidad del índice puede ser negado por las inserciones y actualizaciones más lentas.

vea el artículo de MSDN sobre Tablescan vs Index access.

Edit: Como otros han señalado, la consulta puede beneficiarse de un índice si está realizando consultas de agregación, tales como contar el número de veces que aparece un valor particular. También puede beneficiarse si ordena con frecuencia en una columna en particular.

1

En la columna sugieres, no habría razón para crear una tabla de referencia o de consulta para los datos para evitar la redundancia de datos. Esto haría que su columna sea una clave externa, apuntando hacia el PK de la nueva tabla de búsqueda.

Todas las columnas de clave externa deben indexarse.

De lo contrario, evitaría colocar un índice en condiciones normales en dicha columna.

1

No es necesario crear un índice en una columna BIT.

serías sorprendidos.

he tenido que crear un índice que implica una columna de bits para una consulta como:

SELECT foo.Name FROM foo WHERE foo.Active = 1 

Había alrededor de 300.000 filas de la tabla sin embargo.

+0

¿Qué proporción de las filas hicieron Activa = 1 representan en comparación con otros valores posibles? Sospecho que era un subconjunto relativamente pequeño de la mesa completa. –

+1

No funciona. Lo probé y lo confirmé con MS: los índices de cardinalidad bajos no se tienen en cuenta, sin importar las proporciones. – dkretz

2

James golpeó el clavo en la cabeza. Añadiré que incluso una columna de bit podría beneficiarse de un índice según cómo esté utilizando la tabla. Por ejemplo, si necesita contar el número de filas que tienen un 1 muchas veces a lo largo del día, un índice podría ser útil.Los índices no siempre tratan de encontrar un solo registro; también se pueden usar para agregaciones.

+1

No funcionará. Sé por dolorosa experiencia que SQL Server no usará un índice con cardinalidad 2, incluso si 1 registro tiene el valor "1" y 10 millones de registros tienen el valor "0". – dkretz

+0

@doofledorfer: estoy seguro de que es correcto. ¿Tienes un ejemplo real? –

0

Diría que todo depende de cómo se usa la tabla y de los requisitos generales del sistema. Por ejemplo, si es parte de un JOIN grande y el padre es una gran tabla de tipo de informe, entonces querrá seguro el índice. Si es relativamente pequeño en comparación con las otras tablas en la base de datos, y está muy insertado y raramente leído, entonces es probable que no se desee un índice.

Pero el alcance de la operación entre toda la base de datos frente a los recursos disponibles que se asignarán es el factor de decisión clave. Es la forma en que se comporta esta tabla + índice posible en todo el sistema en comparación con todas sus otras tablas y sus requisitos. Si no se tiene en cuenta el panorama general, se podría matar a todo el sistema tratando de aplicar alguna regla arbitraria simplemente por el simple hecho de aplicar una regla arbitraria.

2

Los índices con cardinalidad baja son muy problemáticos. Si solo hay varios valores posibles, SQL Server casi siempre index-scans, sin importar las proporciones.

Ejemplo: He tenido una tabla con un campo de Estado que solo acepta los valores "A", "N" y "R" (para Activo, Nuevo y Jubilado). Normalmente se acerca a una condición donde 95% eran "R", 4 +% eran "A", y algunos eran "N". SELECCIONAR DONDE estado = 'N' sería escaneo de tabla, no importa qué.

PERO - hay un tipo de índice nuevo llamado Filtered Index, que finalmente se encarga de esta condición. También es útil cuando quiere excluir registros con valores NULL.

0

También debe examinar cuidadosamente sus índices si comienza a experimentar interbloqueos entre las consultas, por lo general entre un SELECT y un INSERT/UPDATE. Un índice mal elegido puede contribuir a puntos muertos, ya que no puede tener un índice en absoluto. Consulte el artículo this knowledge base para obtener información adicional. Generalmente, agregar un índice o modificar sus columnas incluidas ayudará a resolver dichos bloqueos. Asegúrese de examinar el plan de consulta de las consultas afectadas.

0

uno de la mejor manera es usar que mvp vistas en SQL Server i sugest Dont reiniciar el servidor durante una semana y luego ejecutar esta consulta:

USE master; 
Go 
SELECT d.database_id, 
    d.object_id, 
    d.index_handle, 
    d.equality_columns, 
    d.inequality_columns, 
    d.included_columns, 
    d.statement AS fully_qualified_object, 
    gs.* 
FROM sys.dm_db_missing_index_groups g 
JOIN sys.dm_db_missing_index_group_stats gs ON gs.group_handle = g.index_group_handle 
JOIN sys.dm_db_missing_index_details d ON g.index_handle = d.index_handle 

Go 

SELECT mig.index_group_handle, 
    mid.index_handle, 
    migs.avg_total_user_cost AS AvgTotalUserCostThatCouldbeReduced, 
    migs.avg_user_impact AS AvgPercentageBenefit, 
    'CREATE INDEX missing_index_' + CONVERT (varchar, mig.index_group_handle) 
    + '_' + CONVERT (varchar, mid.index_handle) 
    + ' ON ' + mid.statement 
    + ' (' + ISNULL (mid.equality_columns,'') 
    + CASE 
     WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns 
     IS NOT NULL THEN ',' 
     ELSE '' 
    END 
    + ISNULL (mid.inequality_columns, '') 
    + ')' 
    + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement 
FROM sys.dm_db_missing_index_groups mig 
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle 
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle 
Order By migs.avg_user_impact Desc 

continuación, compruebe sus tablas y crear el índice requerd.

0

Ya hay buenas respuestas publicadas aquí ... Solo agregué mis dos centavos ... Ejecute el índice que falta DMV y vea si la tabla que mencionó figura como candidata para crear un nuevo índice y vea la definición de El índice.

De Are you using SQL's Missing Index DMVs?

SELECT 
    migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure, 
    'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle) 
    + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']' 
    + ' ON ' + mid.statement 
    + ' (' + ISNULL (mid.equality_columns,'') 
    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END 
    + ISNULL (mid.inequality_columns, '') 
    + ')' 
    + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement, 
    migs.*, mid.database_id, mid.[object_id] 
FROM sys.dm_db_missing_index_groups mig 
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle 
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle 
WHERE migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) > 10 
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC 
Cuestiones relacionadas