¿Cuál es el efecto de reemplazar índices con índices filtrados (valores no nulos)?


10

Nuestro proyecto ejecuta una base de datos muy grande y muy complicada. Entonces, hace aproximadamente un mes, notamos que el espacio utilizado por las columnas indexadas que contenían valores nulos se estaba volviendo demasiado grande. Como respuesta a eso, escribí un script que buscaría dinámicamente en todos los índices de una sola columna que contengan más del 1% de los valores nulos, luego descartaría y volvería a crear esos índices como índices filtrados con la condición de que el valor NO fuera NULL. Esto eliminaría y recrearía cientos de índices en toda la base de datos y, por lo general, liberaría casi el 15% del espacio utilizado por toda la base de datos.

Ahora tengo dos preguntas sobre esto:

A) ¿Cuáles son las desventajas de usar índices filtrados de esta manera? Supongo que solo mejoraría el rendimiento, pero ¿hay algún riesgo de rendimiento involucrado?

B) Recibimos errores ( 'no se puede eliminar el índice XYZ porque no existe o no tiene permiso' ) al soltar y volver a crear los índices, aunque cuando se verificó después, todo había salido exactamente como se esperaba. ¿Cómo puede pasar esto?

¡Gracias por cualquier ayuda!

Editar: en respuesta a @Thomas Kejser

Hola y gracias, pero resulta que fue un desastre. En ese momento no entendíamos varias cosas como:

  1. Durante una consulta, SQLOS realiza planes de índice antes de determinar que no puede usar valores NULL para unir columnas de tabla. Es decir, realmente necesita tener un filtro de cláusula WHERE que se ajuste al índice para todos y cada uno de los índices filtrados utilizados en la consulta, o el índice no se utilizará en absoluto.
  2. Dejar caer y crear índices y actualizar de forma redundante sus estadísticas una vez más después aún puede no ser suficiente para producir los planes actualizados, lo que asumimos que lo harían. Parece que en algunos casos solo una carga de trabajo lo suficientemente alta obligará a SQL Server a reevaluar los planes.
  3. Hay algunas características exóticas de la funcionalidad del planificador de ejecución que son difíciles de determinar solo por el sentido común y la lógica. Incluso con miles de variaciones generadas por código subyacente de diferentes consultas, los índices aparentemente inútiles pueden ayudar en algunas estadísticas y planes de consulta que terminan siendo utilizados en consultas críticas.

Al final, estos cambios fueron revertidos. Por lo tanto, los índices filtrados son una herramienta poderosa, pero debe comprender realmente exactamente qué datos se obtienen de esas columnas. Donde los índices normales aparte de los problemas de espacio son bastante fáciles de aplicar, los índices filtrados representan soluciones muy personalizadas. Ciertamente no son un reemplazo para un índice regular, sino una extensión para ellos en esas circunstancias especiales que se requieren.


Es posible que desee volver a examinar su estrategia de indexación también. Si tiene cientos de índices de campo único, probablemente no sea óptimo.
JNK

La necesidad de esto proviene del hecho de que la base de datos se hereda parcialmente de otro sistema. De manera predeterminada, tenemos algunas tablas abstractas y varias columnas abstractas que pueden no usarse en absoluto, lo que produce la mayoría de estas cantidades masivas de valores NULL indexados. En cuanto a los índices de campo único, se crean a partir del requisito básico de que cada clave externa debe indexarse, y muchos de ellos están en estas columnas que contienen valores NULL en su mayoría o solo.
Kahn

Respuestas:


8

Enfoque muy interesante. Mi voto a favor de la creatividad.

Dado que recuperó el espacio, supongo que los índices originales ya no están en su lugar. Las desventajas de los índices filtrados son:

En términos prácticos, esto significa que debe ser extremadamente cuidadoso con los índices filtrados ya que a menudo darán como resultado planes de consulta horribles. No iría tan lejos como para llamarlos inútiles, pero los veo como una adición a los índices tradicionales, no como un reemplazo (como está tratando de hacer).


"La parametrización de consultas no funciona con índices filtrados". esto probablemente se puede solucionar con la opción (recompilar)
MichaelD

2

Thomas Kejser responde a este tema más arriba.

Solo pensé en agregar 2 centavos.

He visto que solo se usan algunos índices filtrados (que se muestran en el plan de ejecución) cuando coincide exactamente con la cláusula where en su consulta como el where en el índice filtrado.

¿Has intentado usar vistas indexadas ? columnas dispersas ?

Creo que, en la medida en que solo tenga uniones internas, puede crear una vista indexada que contenga las cláusulas where de sus índices filtrados y luego puede usar la vista en su lugar.

Podría haber más de una vista. Pero al igual que con los índices no agrupados, demasiados retrasarán su escritura.

Según mi experiencia, tendría buenas ganancias en lectura, pero tendría que monitorear las escrituras (inserciones y actualizaciones) especialmente si las tablas están involucradas en la replicación.

Sin embargo, como entiendo que su principal preocupación es, the null valuespor lo tanto, le sugeriría columnas SPARSE en sus índices .

Las columnas dispersas son especialmente apropiadas para índices filtrados.

Como he anunciado columnas dispersas, no me sentiría bien si no le dijera también sobre sus limitaciones:

Al diseñar tablas con columnas dispersas, tenga en cuenta que se requieren 2 bytes adicionales de sobrecarga para cada columna dispersa no nula en la tabla cuando se actualiza una fila.

Como resultado de esto

requisito adicional de memoria, las actualizaciones pueden fallar inesperadamente con el error 576 cuando el tamaño total de la fila, incluida esta sobrecarga de memoria, supera 8019,

y no se pueden empujar columnas de la fila.

Considere el> ejemplo de una tabla que tiene 600 columnas dispersas de tipo bigint.

Si hay 571 columnas no nulas, el tamaño total en el disco es 571 * 12 = 6852 bytes. Después de incluir una sobrecarga de fila adicional y el encabezado de columna dispersa, esto aumenta a alrededor de 6895 bytes. La página todavía tiene alrededor de 1124 bytes disponibles en el disco. Esto puede dar la impresión de que las columnas adicionales se pueden actualizar con éxito. Sin embargo, durante la actualización, hay una sobrecarga adicional en la memoria que es 2 * (número de columnas dispersas no nulas). En este ejemplo, incluir la sobrecarga adicional - 2 * 571 = 1142 bytes - aumenta el tamaño de la fila en el disco a alrededor de 8037 bytes. Este tamaño excede el tamaño máximo permitido de 8019 bytes. Dado que todas las columnas son tipos de datos de longitud fija, no se pueden eliminar de la fila. Como resultado, la actualización falla con el error 576.

más detalles en el enlace de arriba, sin embargo, prefiero publicar aquí esta advertencia también:

Cambiar una columna de dispersa a no dispersa o no dispersa a dispersa requiere cambiar el formato de almacenamiento de la columna.

El Motor de base de datos de SQL Server utiliza el siguiente procedimiento para lograr este cambio:

1: agrega una nueva columna a la tabla en el nuevo tamaño y formato de almacenamiento.

2: para cada fila de la tabla, actualiza y copia el valor almacenado en la columna anterior a la nueva columna.

3 - Elimina la columna anterior del esquema de la tabla.

4 - Reconstruye la tabla (si no hay índice agrupado) o reconstruye el índice agrupado para reclamar el espacio utilizado por la columna anterior.


1
Hola. Un poco tarde para la refriega, pero sí, aunque abandonamos el enfoque descrito en este tema hace mucho tiempo, recientemente volvimos a él con un enfoque más selectivo. Básicamente, observamos el uso de estadísticas y el modelo comercial para confirmar los índices tabla por tabla. Luego lo probé agregando un nuevo índice filtrado en el lado del normal, y lo verifiqué durante algunas semanas cuál terminó siendo utilizado. Después de confirmar que SOLO los índices filtrados se usaron en nuevos planes, descartamos los índices no filtrados normales.
Kahn

1
Además, cambiamos bastantes columnas a tipos dispersos. Sin embargo, el problema con esto es que, como verá en MSDN, modificar un tipo de columna para dispersar básicamente obliga a recrear todo el índice agrupado. Haciendo esto bastante pesado para mesas grandes y complejas. Así que cambiamos el nombre de las restricciones y la tabla, creamos una nueva con el mismo modelo y nombre original pero con columnas dispersas, y luego transferimos los datos a la nueva tabla en lotes apropiados. Luego, una vez comprobado que todo estaba bien y que todos los índices y FK estaban de nuevo en su lugar, abandonaron las tablas antiguas.
Kahn

1
Además, en algunos casos, era preferible utilizar la compresión de página, por lo que terminamos haciéndolo. También es útil, ya que simplemente puede crear el índice agrupado existente con DROP_EXISTING = ON, para que sea mucho, mucho más rápido que ir por la ruta dispersa. Especialmente porque evita toda la molestia de volver a gestionar índices y FK.
Kahn
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.