Patrón de Vista Materializada

Genere vistas rellenadas previamente sobre los datos en uno o varios almacenes de datos cuando los datos no tienen el formato ideal para las operaciones de consulta necesarias. Este enfoque puede admitir consultas y extracción de datos eficaces y mejorar el rendimiento de la aplicación.

Contexto y problema

Al almacenar datos, los desarrolladores y los administradores de datos suelen priorizar cómo se almacenan los datos en lugar de cómo se leen. El formato de almacenamiento elegido normalmente refleja el formato de los datos, los requisitos para administrar el tamaño de los datos y la integridad de los datos, y el tipo de almacén en uso. Por ejemplo, cuando se usa un almacén de documentos de NoSQL, a menudo se representan los datos como una serie de agregados, cada uno que contiene toda la información de esa entidad.

Sin embargo, este enfoque puede tener un efecto negativo en las consultas. Cuando una consulta solo necesita un subconjunto de los datos de algunas entidades, como un resumen de pedidos de varios clientes sin todos los detalles de los pedidos, se deben extraer todos los datos de las entidades pertinentes con el fin de obtener la información necesaria.

Agregar índices o volver a dar forma a las consultas en tiempo de lectura no siempre resuelve esta ineficiencia. Muchos almacenes no se pueden volver a indexar para patrones de lectura arbitrarios sin afectar al rendimiento de escritura. La agregación entre entidades sigue siendo costosa en el momento de la consulta. Algunos almacenes tienen funcionalidades de consulta limitadas por diseño. Debido a estas restricciones, a menudo no basta con optimizar la ruta de lectura únicamente en el propio almacén de origen.

Solución

Para admitir consultas eficaces, una solución común consiste en generar, de antemano, una vista que materialice los datos en un formato adecuado para el conjunto de resultados necesario. El patrón Materialized View describe la generación de vistas de datos previamente rellenadas en entornos en los que los datos de origen no se encuentran en un formato adecuado para consulta, donde la generación de una consulta adecuada es difícil o donde el rendimiento de las consultas es deficiente debido a la naturaleza de los datos o el almacén de datos.

En este patrón, una vista materializada es un modelo de lectura o proyección que conserva los datos derivados de uno o varios almacenes de origen. Un componente de aplicación dedicado o una canalización de datos puede mantener la proyección, incluidos los límites del almacén. Los consumidores de consultas tratan la proyección como de solo lectura. Este concepto arquitectónico es más amplio que un objeto materialized-view nativo de base de datos, que un motor de base de datos define, almacena y actualiza según sus propias restricciones de características.

Estas vistas materializadas, que solo contienen datos requeridos por una consulta, permiten a las aplicaciones obtener rápidamente la información que necesitan. Además de combinar tablas o combinar entidades de datos, las vistas materializadas pueden incluir los valores actuales de columnas calculadas o elementos de datos, los resultados de combinar valores o de ejecutar transformaciones sobre los elementos de datos y los valores especificados como parte de la consulta. Incluso se puede optimizar una vista materializada para una sola consulta.

Un punto clave es que una vista materializada y los datos que contiene son completamente prescindibles, porque pueden reconstruirse por completo a partir de los almacenes de datos de origen. Los consumidores de consultas no actualizan la vista directamente. En su lugar, un componente dedicado, una canalización de datos o un motor de base de datos lo mantiene, por lo que es una caché especializada.

Cuando los datos de origen de la vista cambian, la vista debe actualizarse para incluir la nueva información. Puede programar que esta actualización se produzca automáticamente o cuando el sistema detecte un cambio en los datos originales. En algunos casos, es posible que tenga que volver a generar la vista manualmente. En la ilustración siguiente se muestra un ejemplo de cómo se puede usar el patrón de vista materializada.

Diagrama que muestra un ejemplo de cómo se puede usar el patrón de vista materializada.

Problemas y consideraciones

Tenga en cuenta los siguientes puntos a medida que decida cómo implementar este patrón:

  • Ver la estrategia de actualización. Idealmente, la vista se vuelve a generar en respuesta a un evento que indica un cambio en los datos de origen, aunque este enfoque puede provocar una sobrecarga excesiva si los datos de origen cambian rápidamente. Otra alternativa es usar una tarea programada, un desencadenador externo o una acción manual para regenerar la vista.

  • Comportamiento de actualización. Determine si la implementación realiza una recompilación completa o aplica los cambios incrementalmente. También debe decidir si las operaciones de actualización bloquean las lecturas.

    Estas decisiones determinan si las consultas devuelven datos materializados potencialmente obsoletos, combinan datos materializados con cambios de origen no procesados para devolver los resultados actuales o siguen sirviendo la última versión completa hasta que finalice la actualización.

  • Actualice la confiabilidad de la señal. Si la señal de activación que desencadena la regeneración de la vista se pierde o se retrasa —por ejemplo, por un evento del flujo de cambios omitido o por una tarea programada fallida—, la vista devuelve silenciosamente resultados obsoletos. Supervise cuándo se actualizó por última vez la vista y genere una alerta cuando su antigüedad supere el margen de desactualización aceptable.

  • Recalcular el coste de computación. La regeneración de una vista consume recursos de proceso proporcionales al volumen de datos de origen y a la complejidad de las transformaciones. Para la actualización controlada por eventos en datos de origen que cambian rápidamente o para recompilaciones completas de vistas analíticas de gran tamaño, el costo de proceso de la actualización puede ser un controlador de costos significativo. Ajuste adecuadamente la frecuencia y el alcance de la actualización para equilibrar la actualidad de los datos con el coste de computación.

  • Dependencia de Event Sourcing. En algunos sistemas, como cuando se usa el patrón Event Sourcing para mantener un almacén de solo los eventos que modificaron los datos, las vistas materializadas suelen ser necesarias. La única manera de obtener información del almacén de eventos es rellenar previamente las vistas y examinar todos los eventos para determinar el estado actual. Si no usa Event Sourcing, considere si una vista materializada es útil. Las vistas materializadas tienden a adaptarse específicamente a una o una pequeña cantidad de consultas. Si se usan muchas consultas, las vistas materializadas pueden dar lugar a requisitos de capacidad de almacenamiento y costos de almacenamiento inaceptables.

  • Coherencia de datos. Tenga en cuenta el impacto en la coherencia de los datos al generar la vista y al actualizar la vista si este proceso se produce según una programación. Si los datos de origen cambian al mismo tiempo que se genera la vista, la copia de los datos de la vista no es totalmente coherente con los datos originales. La ventana de obsolescencia máxima es una consecuencia directa del intervalo de actualización o el retraso de procesamiento de eventos, por lo que define la obsolescencia aceptable antes de elegir entre la actualización manual, programada o controlada por eventos.

  • Ver la ubicación de almacenamiento. La vista no tiene que estar ubicada en el mismo almacén o la misma partición que los datos originales. Puede combinar subconjuntos de algunas particiones diferentes.

  • Reconstruir en caso de pérdida. Se puede volver a generar una vista si se pierde. Por lo tanto, si la vista es transitoria y solo se usa para mejorar el rendimiento de las consultas reflejando el estado actual de los datos o para mejorar la escalabilidad, puede almacenarla en una memoria caché o en una ubicación menos confiable.

    Sin embargo, si se produce un error en el proceso de actualización a mitad de camino (por ejemplo, si se bloquea una tarea de regeneración programada), determine si la carga de trabajo debe servir a la vista completa anterior, una vista parcialmente actualizada o ninguna vista en absoluto hasta que la regeneración se realice correctamente.

    El enfoque más seguro suele ser la publicación atómica o el reemplazo con versiones, donde la carga de trabajo sigue sirviendo y usando la última vista completa mientras compila y valida la nueva vista. Cambie a la nueva vista una vez completada la validación.

  • Columnas calculadas. Al definir una vista materializada, maximice su valor agregando elementos de datos o columnas basados en el cálculo o transformación de los elementos de datos existentes, en los valores pasados en la consulta o en combinaciones de estos valores cuando proceda.

  • Ver indexación. Si el mecanismo de almacenamiento lo admite, considere la posibilidad de indexar la vista materializada para mejorar el rendimiento. Muchas bases de datos relacionales admiten la indexación para las vistas. Sin embargo, el mantenimiento de índices en la vista añade sobrecarga en la ruta de escritura durante cada ciclo de actualización, por lo que deben sopesarse las mejoras en el rendimiento de lectura frente al tiempo de actualización adicional y al coste de computación.

  • Control de acceso de las vistas. Cuando se usa una vista materializada para restringir qué subconjuntos de datos son visibles para determinados consumidores, como por motivos de seguridad o privacidad, el almacén de vistas debe aplicar los mismos controles de acceso o más estrictos que los datos de origen. La canalización de actualización debe excluir columnas o filas no deseadas, ya que una vista que incluye datos accidentalmente más allá de su ámbito previsto puede exponer datos protegidos.

  • Ciclo de vida de los datos en las vistas. Aplique los requisitos de retención y eliminación de los datos de origen a cada vista materializada. Propague las eliminaciones y supresiones de origen dentro del plazo requerido, e incluya cada vista en la supervisión del cumplimiento. Para obtener más información, consulte Bases de referencias de seguridad y gobernanza de datos con Microsoft Purview.

  • Ver la administración del ciclo de vida. Considere las definiciones de vistas como artefactos desplegables gestionados mediante control de versiones y canalizaciones de CI/CD, especialmente cuando las vistas se definen de forma declarativa. Sin una gestión del ciclo de vida, las definiciones de las vistas pueden divergir entre entornos, lo que provoca un comportamiento incoherente de las consultas entre desarrollo, preproducción y producción.

Cuándo usar este patrón

Use este patrón cuando:

  • Debe crear vistas sobre los datos difíciles de consultar directamente, o donde las consultas deben ser muy complejas para extraer datos almacenados en una forma normalizada, semiestructurada o no estructurada.
  • Quiere crear proyecciones almacenadas en caché transitorias o recompilables que mejoran el rendimiento de las consultas, o que dan forma a los datos usados para construir objetos de transferencia de datos para una interfaz de usuario, informe o presentación.
  • Debe admitir escenarios con conexión ocasional o sin conexión, en los que la conexión al almacén de datos no siempre está disponible. Puede almacenar en caché localmente la vista en este caso.
  • Quiere simplificar las consultas y exponer datos para la experimentación de una manera que no requiera conocimiento del formato de datos de origen. Por ejemplo, combinar diferentes tablas en una o varias bases de datos, o en uno o varios dominios de almacenes NoSQL, y luego aplicar formato a los datos para adaptarlos a su uso final.
  • Quiere proporcionar acceso a subconjuntos específicos de los datos de origen que, por motivos de seguridad o privacidad, no deben ser accesibles con carácter general, abiertos a modificaciones o totalmente expuestos a los usuarios.
  • Quiere conectar diferentes almacenes de datos para aprovechar sus capacidades específicas. Por ejemplo, puede usar un almacén en la nube que sea eficaz para escribir como almacén de datos de referencia y una base de datos relacional que ofrezca un buen rendimiento de consulta y lectura para contener las vistas materializadas.
  • Cuando se usan microservicios, manténgalos acoplados de forma flexible, incluido su almacenamiento de datos. Las vistas materializadas pueden ayudarle a consolidar los datos procedentes de sus servicios. Si las vistas materializadas no son adecuadas en la arquitectura de los microservicios o en un escenario específico, considere la posibilidad de tener límites bien definidos que se alinean con el diseño controlado por dominio (DDD) y agregar sus datos a petición.

Este patrón podría no ser adecuado cuando:

  • Los datos de origen son sencillos y fáciles de consultar.
  • Los datos de origen cambian muy rápidamente o es posible acceder a ellos sin usar una vista. En estos casos, evite la sobrecarga de procesamiento que supone crear vistas.
  • La coherencia tiene una prioridad alta. Las vistas podrían no ser siempre completamente coherentes con los datos originales.

Diseño de cargas de trabajo

Un arquitecto debe evaluar cómo se puede usar el patrón Materialized View en el diseño de su carga de trabajo para abordar los objetivos y principios descritos en los pilares del Marco de buena arquitectura de Azure. Por ejemplo:

Fundamento Cómo apoya este patrón los objetivos de los pilares
Eficiencia del rendimiento ayuda a su carga de trabajo a satisfacer eficientemente las demandas mediante optimizaciones en el escalado, los datos y el código. Las vistas materializadas almacenan los resultados de cálculos complejos o consultas sin necesidad de que el motor de base de datos o el cliente vuelvan a realizar el cálculo para cada solicitud. Este diseño reduce el consumo general de recursos.

- PE:08 Rendimiento de datos

Si este patrón introduce concesiones dentro de un pilar, considérelas en relación con los objetivos de los otros pilares.

Example

Considere una aplicación de ventas que almacena las entidades Order, OrderItem y Customer en Azure Table Storage. Los pedidos se particionan por identificador de cliente, elementos de pedido por identificador de pedido y clientes por región. Estas claves admiten los patrones de acceso operativo de la aplicación, pero un informe de ventas agrupado por producto debe leer datos entre particiones y combinarlos en el código de la aplicación.

En la ilustración siguiente se muestra una vista materializada que almacena el valor total de ventas y el número de clientes de compra distintos para cada producto de la categoría Electrónica. Las filas de origen y los valores de resumen son ilustrativas, no un conjunto de datos de entrada completo para los totales mostrados.

Diagrama que muestra las tablas Order, OrderItem y Customer combinadas en un resumen de ventas materializado particionado por categoría de producto.

Un proceso en segundo plano lee las entidades de origen necesarias, asocia los elementos de pedido a sus pedidos y clientes, y agrega las ventas por producto. Cuenta a cada cliente una sola vez por producto, incluso cuando ese cliente tiene varios pedidos o varias líneas de pedido. El proceso escribe los resultados en una tabla de resumen independiente con la categoría de producto como PartitionKey y el identificador de producto como RowKey. Esta tabla de resumen es una proyección mantenida por la aplicación, no una vista materializada nativa de base de datos.

A continuación, un panel puede consultar la partición Electrónica en lugar de repetir las lecturas y agregaciones entre particiones para cada solicitud. Una búsqueda de un producto proporciona ambas claves. Para ver las implicaciones de rendimiento de las consultas de estas claves, consulte Diseño para consultas.

Actualice el resumen según una programación que cumpla la ventana de obsolescencia aceptable del informe. Compile y valide una nueva versión antes de publicarla, por lo que los lectores siguen usando la versión completa anterior durante una recompilación. La actualización sigue implicando costes de lectura y agregación entre particiones, pero las consultas repetidas del informe reutilizan el resultado. Los cambios de origen no son visibles hasta que una actualización posterior las incluya.

Pasos siguientes

Los patrones siguientes también le serán pertinentes cuando implemente este patrón:

  • Patrón de Segregación de Responsabilidades de Comando y Consulta (CQRS). Utilizar para actualizar la información en una vista materializada respondiendo a los eventos que se producen cuando cambian los valores de los datos subyacentes.
  • Patrón de originación de eventos. Use junto con el patrón CQRS para mantener la información en una vista materializada. Cuando cambian los valores de datos en los que se basa una vista materializada, el sistema puede generar eventos que describan estos cambios y guardarlos en un almacén de eventos.
  • Patrón de Tabla de Índice. Normalmente, los datos de una vista materializada se organizan mediante una clave principal, pero puede que las consultas tengan que recuperar información de esta vista examinando los datos de otros campos. Use este patrón para crear índices secundarios a través de conjuntos de datos para almacenes de datos que no admiten índices secundarios nativos.