2011-07-18 11 views
6

Esta pregunta se refiere a diseño de índices no agrupados en SQL Server 2005.SQL Server no agrupado diseño de índices

tengo una gran mesa con varios millones de líneas. Las filas solo se leen o insertan. La mayoría de las operaciones son lecturas. He estado consultando las diversas consultas SELECT que acceden a la tabla con el objetivo de mejorar la velocidad de acceso de lectura. El espacio en disco no es realmente un problema. (Cada fila tiene una ID única, y la estoy utilizando como el único campo en el índice agrupado).

Mi pregunta es si un índice no agrupado indexa más columnas de las que utiliza una consulta, ¿eso se traduce? en una ejecución de consulta más lenta que un índice que coincide exactamente con la consulta?

A medida que aumenta el número de consultas distintas, también lo hace el número de permutaciones de columnas utilizadas en sus cláusulas WHERE. No estoy seguro acerca de las compensaciones entre tener muchos índices con un pequeño número de columnas (uno para cada consulta) versus menos índices en más columnas.

Por ejemplo, supongo que tengo dos consultas SELECT. La primera usa las columnas A, B, C y D en su cláusula WHERE, y la segunda usa A, B, E y F. Sería mejor practicar aquí definir dos índices, uno en A/B/C/D y el otro en A/B/E/F; o un solo índice en A/B/C/D/E/F?

+0

¡Gran pregunta! Esta no es realmente una respuesta, pero Kimberly Tripp ha escrito varios artículos brillantes sobre indexación de SQL que tal vez quiera consultar. Aquí hay solo uno: http://www.sqlskills.com/blogs/kimberly/Default.aspx#p4 – Yuck

Respuesta

3

Lo primero es lo primero, el orden de las columnas en los índices es importante. Por lo tanto, crear/ajustar sus consultas en consecuencia le permitirá hacer un buen uso de los índices que ha creado.

Si tener dos índices por separado o un índice depende de las dependencias de las columnas en disputa y del tipo de consultas que se ejecutan. En su ejemplo, si las columnas E y F se relacionan con o dependen de las columnas C y D, entonces tiene sentido tener un índice que cubra todas las columnas.

+0

¡Gracias por tu respuesta! Dos preguntas de seguimiento: 1. Cuando dice que importa el orden de las columnas, ¿quiere decir el orden en que aparecen las columnas, o el orden de clasificación, o ambos? 2. Cuando dice "si las columnas E y F se relacionan con o dependen de C y D", ¿qué tipo de relación es significativa? Los valores en (por ejemplo) C/D/E/F son independientes entre sí, pero cada columna tiene duplicados. –

+0

1. Sí, el orden en que aparecen las columnas en su instrucción CREATE INDEX. Asegúrese de que sus consultas utilicen el mismo orden en la cláusula WHERE para sacar el máximo beneficio de Index. 2. Cuando dije una relación entre campos, un ejemplo simple sería encontrar a Jason Bourne, usaría un índice que use un índice que tenga LASTNAME, FIRSTNAME en el mismo orden y luego use la consulta WHERE LASTNAME = 'Bourne' Y FIRSTNAME = ' Jason '. Si lo piensa usando DONDE en orden inverso al anterior, no podrá utilizar el índice para obtener el máximo beneficio. –

+0

(... cont.) El orden en que las columnas entran en el índice depende del negocio. Imagine una ciudad con el 70% de las personas con el apellido BOURNE. Entonces, en realidad, tiene sentido usar el índice con las columnas FIRSTNAME, LASTNAME en el orser. –

1

Mi pregunta es, si un índice no agrupado indexa más columnas que las utilizadas por una consulta, ¿eso se traduce en una ejecución de consulta más lenta que un índice que coincide exactamente con la consulta?

No, tener más columnas no ralentiza el tiempo de consulta para las consultas que usan las primeras 1, 2, n columnas en el índice. Dicho esto, si tiene poca memoria, la carga del índice en la memoria puede hacer que otras cosas queden fuera de la memoria y ralentizar la consulta, pero si tiene mucha memoria, esto no debería ser un problema.

A medida que aumenta el número de consultas distintas, también lo hace el número de permutaciones de columnas utilizadas en sus cláusulas WHERE. No estoy seguro acerca de las compensaciones entre tener muchos índices con un pequeño número de columnas (uno para cada consulta) versus menos índices en más columnas.

Primero debe agregar los campos únicos consultados con más frecuencia en los índices. Menos índices con muchas columnas pueden no darle lo que desea.

por ejemplo, si usted tiene un índice con las siguientes columnas:

  • ColumnA
  • ColumnB
  • ColumnC
  • ColumnD
  • ColumnE
  • ColumnF

en ese orden, las consultas que filtran contra ColumnA, ColumnB, ColumnC, ColumnD ... usarán el índice, pero si solo está consultando ColumnE o ColumnF, no usará el índice.

Adoptar un enfoque diffferent si tiene seis índices en una sola tabla, cada uno con una sola columna

  • Índice1 - ColumnA
  • índice 2 - ColumnB
  • Index3 - ColumnC
  • Index4 - ColumnD
  • Index5 - ColumnE
  • Index6 - ColumnF

En este caso, solo uno de esos 6 índices se utilizará para cualquier consulta.

Además, si el índice contiene un valor que no es muy selectivo, es posible que no lo ayude. Por ejemplo, si tiene una columna llamada GENDER que puede contener los siguientes valores (masculino, femenino y desconocido), probablemente no le ayude a incluir esta columna en el índice. Cuando se ejecuta la consulta, SQL Server puede determinar que la columna no es lo suficientemente selectiva y solo asumir que una exploración de tabla completa sería más rápida.

Hay muchas maneras de averiguar qué índices está utilizando la consulta, pero un enfoque que uso es mirar los índices que nunca se utilizan. Ejecute la siguiente consulta en su base de datos y descubra si realmente se están utilizando los índices que cree que se están utilizando.

SELECT iv.table_name, 
     i.name       AS index_name, 
     iv.seeks + iv.scans + iv.lookups AS total_accesses, 
     iv.seeks, 
     iv.scans, 
     iv.lookups, 
     t.indextype, 
     t.indexsizemb 
FROM (SELECT i.object_id, 
       Object_name(i.object_id) AS table_name, 
       i.index_id, 
       SUM(i.user_seeks)  AS seeks, 
       SUM(i.user_scans)  AS scans, 
       SUM(i.user_lookups)  AS lookups 
     FROM sys.tables t 
       INNER JOIN sys.dm_db_index_usage_stats i 
        ON t.object_id = i.object_id 
     GROUP BY i.object_id, 
        i.index_id) AS iv 
     INNER JOIN sys.indexes i 
      ON iv.object_id = i.object_id 
      AND iv.index_id = i.index_id 
     INNER JOIN (SELECT sys_schemas.name AS schemaname, 
          sys_objects.name AS tablename, 
          sys_indexes.name AS indexname , 
          sys_indexes.type_desc AS indextype , 
    CAST(partition_stats.used_page_count * 8/1024.00 AS DECIMAL(10, 3)) AS indexsizemb 
FROM sys.dm_db_partition_stats partition_stats 
INNER JOIN sys.indexes sys_indexes 
    ON partition_stats.[object_id] = sys_indexes.[object_id] 
     AND partition_stats.index_id = sys_indexes.index_id 
     AND sys_indexes.type_desc <> 'HEAP' 
INNER JOIN sys.objects sys_objects 
    ON sys_objects.[object_id] = partition_stats.[object_id] 
INNER JOIN sys.schemas sys_schemas 
    ON sys_objects.[schema_id] = sys_schemas.[schema_id] 
     AND sys_schemas.name <> 'SYS') AS t 
ON t.indexname = i.name 
AND t.tablename = iv.table_name 
--WHERE t.IndexSizeMB > 200 
WHERE iv.seeks + iv.scans + iv.lookups = 0 
ORDER BY total_accesses ASC; 

lo general localizar a índices que no se hayan usado, o no se han utilizado varios meses después de reiniciar SQL Server, y determinar si se deben eliminar o no. A veces, demasiados índices pueden ralentizar SQL Server averiguando la mejor ruta para ejecutar una consulta, y eliminar los índices no utilizados puede acelerar ese proceso.

Espero que esto ayude a dar sentido a sus índices.

1

Las respuestas existentes ya son muy buenas. Aquí hay una idea nueva: encontrar un conjunto óptimo de índices bajo cierta carga de trabajo y disponibilidad de memoria es un problema difícil que requiere una búsqueda exhaustiva de un gran espacio de búsqueda.

El Asistente de ajuste del motor de base de datos (DTA) implementa exactamente eso! Te recomiendo que grabes una carga de trabajo representativa (¡incluidas las escrituras!) Y permitas que el DTA te dé sugerencias. Tomará espacio de disco en la cuenta, también.

1

El espacio en disco no es realmente un problema.

Por favor, no piense de esta manera. No importa si tiene 500 GB de espacio libre. Cuanto más grande es una tabla o índice, más tiempo lleva leer desde el disco Y cuanto más espacio ocupa en la memoria (es decir, el conjunto de almacenamiento intermedio) Y las lecturas más lógicas que llevará a satisfacer la consulta. Para más detalles sobre este tema, mira aquí: http://www.sqlservercentral.com/articles/data-modeling/71725/

(Cada fila tiene un identificador único, y estoy usando eso como un único campo en el índice agrupado.)

son los mas de sus consultas utilizando esa ID en una cláusula WHERE? De lo contrario, podría no ser una buena opción para el índice agrupado.

Mi pregunta es, si un índices no agrupados índice más columnas que son utilizado por una consulta, se traduce esto en la ejecución de la consulta más lento que un índice que coincide exactamente con la consulta?

Depende de algunos factores. ¿De cuántos más campos estás hablando? ¿Un solo campo TINYINT que es de 1 byte? O varios campos que componen 300 bytes? A menos que esté usando Índices filtrados, necesita multiplicar el tamaño de su índice más el tamaño de su índice agrupado (para índices no ÚNICOS) por el número de filas. Como mencioné anteriormente, más espacio ocupado significa más lento, pero de manera realista, 5 MB extra en 100 MB probablemente no tengan una diferencia notable.

Tenga en cuenta que el diseño del índice es arte y ciencia. Debe tener en cuenta qué consultas se ejecutarán con más frecuencia y qué ORDER BYs se utilizan, así como las cláusulas WHERE. Debe tener en cuenta que no se usará un índice si la columna principal no está presente en la consulta, incluso si el resto de los campos del índice están en la consulta.

En términos generales, usted no desea indexar cada campo individual porque:

  1. demasiados índices ralentizan las operaciones DML, que es un problema incluso si la mayoría de las operaciones son SELECT en esta tabla
  2. demasiados índices aumenta las posibilidades de cerrojos muertos
  3. una consulta que solicite 4 campos no va a utilizar 4 índices separados. la mayoría de las veces el optimizador elige el que se siente funcionará mejor y, a veces puede optar por unirse a dos de ellos juntos, especialmente si usted tiene una condición OR

Por ejemplo, decir que tengo dos consultas SELECT. El primero utiliza las columnas A, B, C y D en su cláusula WHERE, y la segunda utiliza A, B, E y F.

Se podría hacer mejor por la indexación simplemente A y B y ver cómo eso funciona Si esa combinación es única, considérela como una posibilidad para un índice agrupado compuesto. Si no son únicos, pero la mayoría de las consultas los utilizan, considere crear el índice agrupado: A, B, IDfield. Si se incluye el IDfield por último, la combinación es única. Esto es importante porque si su índice agrupado no es una clave principal, REALMENTE necesita declarar el índice agrupado como ÚNICO, por lo que no tiene el campo de unificador oculto. Una clave principal es, por definición, única.

Consulte también la opción INCLUIR para Índices.

Y sí, el orden de las columnas es importante ya que determina cómo se organiza el índice. Piense en la diferencia entre tener ActionDate, CustomerID vs CustomerID, ActionDate. Si ActionDate es primero, entonces es más fácil encontrar todos los ID de cliente dentro de un cierto rango de fechas. Pero si solo se preocupa por un cliente y desea varias fechas diferentes de su información, debería omitir ese índice completo, ya que sus datos se distribuirán entre ellos. En ese caso, sería mejor que primero con CustomerID, ya que puede reducir más rápidamente a donde comienzan sus datos y luego simplemente tomar los datos que desea según las fechas.

Pero no, el orden de su condición WHERE NO tiene relación con el uso o no de un índice. SQL Server usa un optimizador basado en costos que escanea todas las condiciones y usa estadísticas de los índices (la columna principal) para determinar cuál debería ser el plan más apropiado.

Por último, asegúrese de PROBAR varias estrategias. No intentes solo una cosa y sigue adelante. Fuiste muy general en tu descripción, incluso sin dar los tipos de datos para los campos o cómo se usan los campos, por lo que cualquier recomendación aquí que sea altamente específica es cuestionable. Use SET STATISTICS IO ON y busque Lectura lógica. ¡Cuanto menor sea ese número, mejor!

Cuestiones relacionadas