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 BY
en 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?
SELECT
yCREATE VIEW
están equivocados, ya que creo que es tuCREATE INDEX
guión.Respuestas:
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.
fuente
Las respuestas de Aarons cubrieron bien esta pregunta. Dos cosas para agregar:
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.
fuente