Usar vistas indizadas para agregados: ¿demasiado bueno para ser verdad?


28

Tenemos un almacén de datos con un recuento de registros bastante grande (10-20 millones de filas) y, a menudo, ejecutamos consultas que cuentan registros entre ciertas fechas o cuentan registros con ciertas banderas, por ejemplo

SELECT
    f.IsFoo,
    COUNT(*) AS WidgetCount
FROM Widgets AS w
JOIN Flags AS f
    ON f.FlagId = w.FlagId
WHERE w.Date >= @startDate
GROUP BY f.IsFoo

El rendimiento no es horrible, pero puede ser relativamente lento (quizás 10 segundos en un caché frío).

Recientemente descubrí que puedo usar GROUP BYen vistas indexadas y probé algo similar a lo siguiente

CREATE VIEW TestView
WITH SCHEMABINDING
AS
    SELECT
        Date,
        FlagId,
        COUNT_BIG(*) AS WidgetCount
    FROM Widgets
    GROUP BY Date, FlagId;
GO

CREATE UNIQUE CLUSTERED INDEX PK_TestView ON TestView
(
    Date,
    FlagId
);

Como resultado, el rendimiento de mi primera consulta ahora es <100ms, y la vista e índice resultante es <100k (aunque nuestro recuento de filas es grande, el rango de fechas e ID de marcas significa que esta vista solo contiene 1000-2000 filas).

Pensé que tal vez esto podría afectar el rendimiento de las escrituras en la tabla Widget, pero no, el rendimiento de las inserciones y actualizaciones en esta tabla no se ve afectado por lo que pude ver (además, al ser un almacén de datos, esta tabla se actualiza con poca frecuencia de todas formas)

Para mí, esto parece demasiado bueno para ser verdad, ¿verdad? ¿Con qué debo tener cuidado al usar vistas indexadas de esta manera?


2
¿Puedes reescribir tus scripts para que sean SQL válidos? Tus guiones SELECTy CREATE VIEWestán equivocados, ya que creo que es tu CREATE INDEXguión.
Mark Sinkinson

2
@MarkSinkinson Disculpas, resulta que tratar de escribir SQL válido para tablas imaginarias es difícil
Justin

La parte 'demasiado bueno para ser verdad' para mí vino cuando quería vistas más avanzadas, como las que contienen MAX, autoensambladuras externas, o indexar una vista que hace referencia a otra vista, todas las cuales en SQL Server al menos no son permitido docs.microsoft.com/en-us/sql/relational-databases/views/… . Así que siempre termino siendo demasiado ambicioso y luego tengo que reducir las cosas. Pero para las agregaciones más simples son realmente geniales, incluso SUM es compatible.
Simon_Weaver

Respuestas:


29

Como ha notado, la vista en sí solo materializa un pequeño número de filas, por lo que incluso si actualiza toda la tabla, la E / S adicional relacionada con la actualización de la vista es insignificante. Probablemente ya haya sentido el mayor dolor que va a sentir cuando creó la vista. El próximo más cercano será si agrega miles de millones de filas a la tabla base con un grupo de ID nuevos que requieren nuevas filas en la vista.

Esto no es demasiado bueno para ser verdad. Está utilizando vistas indizadas exactamente como estaban destinadas a ser utilizadas, o al menos una de las formas más efectivas: pagar futuras agregaciones de consultas en el momento de la escritura. Esto funciona mejor cuando el resultado es mucho más pequeño que la fuente y, por supuesto, cuando las agregaciones se solicitan con más frecuencia que la actualización de los datos subyacentes (generalmente, más en DW que en OLTP).

Desafortunadamente, muchas personas piensan que indexar una vista es mágico: un índice no hará que todas las vistas sean más eficientes, especialmente las vistas que simplemente unen tablas y / o producen el mismo número de filas que la fuente (o incluso se multiplican). En estos casos, la E / S de la vista es la misma o incluso peor que la consulta original, no solo porque hay la misma o más filas, sino que a menudo también almacenan y materializan más columnas. Por lo tanto, materializarlos por adelantado no proporciona ninguna ganancia, ya que, incluso con SSD, la E / S, la red y el procesamiento / representación del cliente siguen siendo los principales cuellos de botella para devolver grandes conjuntos de resultados al cliente. Los ahorros que obtienes al evitar la unión en tiempo de ejecución simplemente no son medibles en comparación con todos los demás recursos que todavía estás usando.

Al igual que los índices no agrupados, solo tenga cuidado de no hacerlo en exceso. Si agrega 10 vistas indexadas diferentes a una tabla, verá más impacto en la parte de escritura de su carga de trabajo, especialmente si las columnas de agrupación no están (en) la clave de agrupación.

Gosh, he querido bloguear sobre este tema.


19

Las respuestas de Aarons cubrieron bien esta pregunta. Dos cosas para agregar:

  1. Las vistas indizadas de agregación pueden conducir a contenciones entre filas y puntos muertos. Normalmente, dos inserciones no se estancan (excepto por condiciones bastante raras como la escalada de bloqueo o las colisiones de hash de bloqueo). Pero si ambas inserciones abordan el mismo grupo en la vista, contendrán. El mismo punto representa cualquier otra cosa que tenga bloqueos (DML, sugerencias de bloqueo).
  2. Las vistas indizadas que no se agregan también pueden ser útiles. Le permiten indexar en columnas de múltiples tablas. De esa manera, puede filtrar eficientemente en una tabla y ordenar por una columna de una tabla unida. Ese patrón puede convertir la unión de la tabla completa en pequeñas consultas de tiempo constante.

He utilizado vistas de agregación y unión con un beneficio extremo.

En general, su caso de uso parece un caso perfecto. Las vistas indexadas son una técnica muy poco utilizada.

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.