Padrão de Vista Materializada

Gerar vistas pré-populadas sobre dados num ou mais repositórios de dados quando os dados não têm o formato ideal para as operações de consulta necessárias. Esta abordagem pode suportar consultas eficientes e extração de dados e melhorar o desempenho da aplicação.

Contexto e problema

Ao armazenar dados, os programadores e administradores de dados costumam priorizar como os dados são armazenados em vez de como são lidos. O formato de armazenamento escolhido geralmente reflete o formato dos dados, os requisitos para gerir o tamanho e a integridade dos dados, e o tipo de armazenamento em uso. Por exemplo, quando usa um armazenamento de documentos NoSQL, muitas vezes representa os dados como uma série de agregados, cada um contendo toda a informação dessa entidade.

No entanto, esta abordagem pode ter um efeito negativo nas consultas. Quando uma consulta necessita apenas de um subconjunto dos dados de algumas entidades, tal como um resumo das encomendas de vários clientes sem todos os detalhes da encomenda, esta deve extrair todos os dados das entidades relevantes de forma a obter as informações necessárias.

Adicionar índices ou remodelar consultas em tempo de leitura nem sempre resolve esta ineficiência. Muitos sistemas de armazenamento não podem ser reindexados para padrões de leitura arbitrários sem afetar o desempenho de escrita. A agregação entre entidades continua a ser dispendiosa no momento da consulta. Algumas lojas têm capacidades limitadas de consulta por design. Devido a estas restrições, otimizar apenas o caminho de leitura dentro do armazenamento de origem é frequentemente insuficiente.

Solução

Para suportar uma consulta eficiente, uma solução comum é gerar, antecipadamente, uma vista que materialize os dados num formato adequado ao conjunto de resultados desejado. O padrão de Vista Materializada descreve a geração das vistas pré-preenchida de dados em ambientes onde os dados de origem não estão num formato adequado para consultas, onde é difícil criar uma consulta adequada ou onde o desempenho das consultas é fraco devido à natureza dos dados ou do arquivo de dados.

Neste padrão, uma vista materializada é um modelo de leitura ou projeção que persiste dados derivados de um ou mais armazenamentos fonte. Um componente de aplicação dedicado ou um pipeline de dados pode manter a projeção, inclusive entre diferentes armazenamentos de dados. Os consumidores de consulta tratam a projeção como apenas de leitura. Este conceito arquitetónico é mais amplo do que um objeto de visualização materializada nativo da base de dados, que um motor de base de dados define, armazena e atualiza de acordo com as suas próprias restrições de funcionalidades.

Estas vistas materializadas, que contêm apenas dados necessários por uma consulta, permitem às aplicações obter rapidamente a informação de que necessitam. Além de unirem tabelas ou combinarem entidades de dados, as vistas materializadas podem incluir os valores atuais das colunas calculadas ou dos itens de dados, os resultados da combinação de valores ou da execução das transformações nos itens de dados e os valores especificados como parte da consulta. Uma visualização materializada pode até ser otimizada para uma única consulta.

Um ponto chave é que uma vista materializada e os dados que contém são completamente descartáveis porque podem ser totalmente reconstruídos a partir dos armazenamentos de dados de origem. Os consumidores de consultas não atualizam diretamente a visualização. Em vez disso, um componente dedicado, uma pipeline de dados ou um motor de base de dados mantém-na, pelo que se trata de uma cache especializada.

Quando os dados de origem da vista mudam, esta deve ser atualizada para incluir a nova informação. Pode agendar esta atualização para acontecer automaticamente ou quando o sistema detetar uma alteração nos dados originais. Em alguns casos, pode ser necessário regenerar a vista manualmente. A figura seguinte mostra um exemplo de como o padrão Materialized View pode ser utilizado.

Diagrama que mostra um exemplo de como o padrão Materialized View pode ser utilizado.

Problemas e considerações

Considere os seguintes pontos ao decidir como implementar este padrão:

  • Ver estratégia de atualização. Idealmente, a vista regenera-se em resposta a um evento que indique uma alteração nos dados de origem, embora esta abordagem possa levar a uma sobrecarga excessiva se os dados de origem mudarem rapidamente. Em alternativa, considere utilizar uma tarefa agendada, um acionador externo ou uma ação manual para regenerar a vista.

  • Atualize o comportamento. Determine se a implementação realiza uma reconstrução total ou aplica alterações de forma incremental. Também é necessário decidir se as operações de atualização bloqueiam as operações de leitura.

    Estas decisões determinam se as consultas retornam dados materializados potencialmente obsoletos, combinam dados materializados com alterações de fonte não processadas para devolver resultados atuais, ou continuam a servir a última versão completa até ao fim da atualização.

  • Atualizar a fiabilidade do sinal. Se o sinal de ativação que desencadeia a regeneração da vista se perder ou sofrer um atraso — por exemplo, devido à perda de um evento do feed de alterações ou a uma falha numa tarefa agendada — a vista devolve resultados desatualizados sem aviso. Monitorize a atualização da recência e alerte quando a idade da visualização ultrapassar a janela aceitável de estagnação.

  • Atualizar custo de computação. A regeneração de uma vista consome recursos computacionais proporcionais ao volume de dados fonte e à complexidade das transformações. Para atualização orientada por eventos em dados fonte em rápida mudança, ou para reconstruções completas de grandes visualizações analíticas, o custo computacional da atualização pode ser um fator de custo significativo. Ajuste o tamanho correto da frequência e do âmbito das atualizações para equilibrar a frescura dos dados com os gastos computacionais.

  • Dependência de Event Sourcing. Em alguns sistemas, como quando se utiliza o padrão Event Sourcing para manter um armazenamento apenas dos eventos que modificaram os dados, as visualizações materializadas são tipicamente necessárias. O pré-preenchimento das vistas ao examinar todos os eventos para determinar o estado atual pode ser a única forma de obter informações do arquivo de eventos. Se não estiver a usar Event Sourcing, considere se uma visualização materializada é útil. As visualizações materializadas tendem a ser especificamente adaptadas a uma ou um pequeno número de questões. Se forem utilizadas muitas consultas, as vistas materializadas poderão resultar em requisitos de capacidade de armazenamento e custos de armazenamento inaceitáveis.

  • Consistência dos dados. Considere o impacto na consistência dos dados ao gerar a vista e, ao atualizá-la, se este processo ocorre num calendário. Se os dados de origem mudarem ao mesmo tempo que a visualização é gerada, a cópia dos dados na visualização não é totalmente consistente com os dados originais. A janela máxima de estagnação é consequência direta do intervalo de atualização ou do atraso no processamento de eventos, por isso defina a estagnação aceitável antes de escolher entre atualização orientada por eventos, agendada ou manual.

  • Ver localização de armazenamento. A vista não tem de estar localizada no mesmo arquivo ou na mesma partição que os dados originais. Podes combinar subconjuntos de algumas partições diferentes.

  • Reconstruir após perda. Uma vista pode ser reconstruída se for perdida. Portanto, se a vista for transitória e for usada apenas para melhorar o desempenho da consulta, refletindo o estado atual dos dados, ou para melhorar a escalabilidade, pode armazená-la numa cache ou num local menos fiável.

    No entanto, se o próprio processo de atualização falhar a meio — por exemplo, se uma tarefa de regeneração agendada falhar — determine se a carga de trabalho deve disponibilizar a visualização completa anterior, uma visualização parcialmente atualizada ou nenhuma visualização até a regeneração ser concluída com êxito.

    A abordagem mais segura é tipicamente a publicação atómica ou a substituição versionada, onde a sua carga de trabalho continua a servir e utiliza a última vista completa enquanto constrói e valida a nova vista. Mude para a nova vista depois de concluir a validação.

  • Colunas computadas. Ao definir uma vista materializada, maximizar o seu valor adicionando itens de dados ou colunas com base no cálculo ou transformação de itens de dados existentes, nos valores passados na consulta, ou em combinações desses valores, quando apropriado.

  • Indexação de vistas. Quando suportado pelo mecanismo de armazenamento, considere indexar a vista materializada para melhorar ainda mais o desempenho. Muitas bases de dados relacionais suportam indexação para visualizações. No entanto, a manutenção do índice na vista adiciona sobrecarga ao caminho de escrita durante cada ciclo de atualização, pelo que equilibra os ganhos de desempenho de leitura com o tempo adicional de atualização e o custo de computação.

  • Controlo de acesso nas vistas. Quando uma visualização materializada é usada para restringir quais subconjuntos de dados são visíveis para certos consumidores, por exemplo, por razões de segurança ou privacidade, o armazenamento de visualizações deve aplicar os mesmos controlos de acesso ou mais rigorosos que os dados de origem. O seu pipeline de atualização deve excluir colunas ou linhas não intencionais, porque uma vista que inclua acidentalmente dados para além do âmbito pretendido pode expor dados protegidos.

  • Ciclo de vida dos dados nas visualizações. Aplique os requisitos de retenção e eliminação dos dados de origem a todas as visualizações materializadas. Propague as eliminações e ocultações de origem dentro do período exigido e inclua cada visualização na monitorização da conformidade. Para mais informações, consulte Regras de base de governação de dados e segurança com a Microsoft Purview.

  • Veja a gestão do ciclo de vida. Trate as definições de views como artefactos passíveis de implementação, geridos por meio de controlo de versões e de pipelines de CI/CD, especialmente quando as views são definidas declarativamente. Sem gestão do ciclo de vida, as definições de visualização podem divergir entre ambientes, causando um comportamento inconsistente das consultas nos ambientes de desenvolvimento, staging e produção.

Quando utilizar este padrão

Utilize este padrão quando:

  • É necessário criar vistas sobre dados que são difíceis de consultar diretamente, ou onde as consultas devem ser muito complexas para extrair dados armazenados de forma normalizada, semi-estruturada ou não estruturada.
  • Queres criar projeções em cache reconstruídas ou transitórias que melhorem o desempenho das consultas, ou que moldem dados usados para construir objetos de transferência de dados para uma interface, relatório ou display.
  • Tens de suportar cenários com ligação ocasional ou sem ligação, em que a ligação ao repositório de dados nem sempre está disponível. Neste caso, podes armazenar a visualização em cache localmente.
  • Queres simplificar consultas e expor dados para experimentação de uma forma que não exija conhecimento do formato dos dados de origem. Por exemplo, ao associar diferentes tabelas numa ou mais bases de dados ou num ou mais domínios nos arquivos NoSQL e, em seguida, formatar os dados para que se adequem à sua eventual utilização.
  • Quer fornecer acesso a subconjuntos específicos dos dados de origem que, por razões de segurança ou privacidade, não devem ser geralmente acessíveis, sujeitos a modificação ou totalmente expostos aos utilizadores.
  • Queres criar pontes entre diferentes armazenamentos de dados para tirar partido das suas capacidades individuais. Por exemplo, pode utilizar um armazenamento na cloud eficiente para a escrita como repositório de dados de referência e uma base de dados relacional que oferece bom desempenho nas consultas e na leitura para armazenar as vistas materializadas.
  • Quando utiliza microserviços, mantenha-os fracamente acoplados, incluindo no que diz respeito ao armazenamento de dados. As vistas materializadas podem ajudar a consolidar os dados dos seus serviços. Se as visualizações materializadas não forem adequadas na sua arquitetura de microserviços ou cenário específico, considere ter limites bem definidos que se alinhem com o design orientado por domínio (DDD) e agregar os seus dados a pedido.

Este padrão pode não ser adequado quando:

  • A origem de dados é simples e fácil de consultar.
  • A origem de dados é alterada muito rapidamente ou pode ser acedida sem utilizar uma vista. Nestes casos, evite a sobrecarga de processamento associada à criação de vistas.
  • A consistência é uma prioridade alta. As vistas podem não estar sempre totalmente consistentes com os dados originais.

Design da carga de trabalho

Um arquiteto deve avaliar como o padrão de Visualização Materializada pode ser utilizado no design da sua carga de trabalho para abordar as metas e os princípios cobertos nos pilares do Azure Well-Architected Framework. Por exemplo:

Pilar Como esse padrão suporta os objetivos do pilar
A Eficiência de Desempenho ajuda sua carga de trabalho a atender às demandas de forma eficiente por meio de otimizações em escala, dados e código. As visualizações materializadas armazenam os resultados de cálculos ou consultas complexas sem exigir que o mecanismo de banco de dados ou o cliente recalcule para cada solicitação. Esse design reduz o consumo geral de recursos.

- PE:08 Desempenho de Dados

Se este padrão introduzir compensações dentro de um pilar, considere-as em relação aos objetivos dos outros pilares.

Example

Considere uma aplicação de vendas que armazena as entidades Order, OrderItem e Customer no Armazenamento de Tabelas do Azure. As encomendas são particionadas por ID de cliente, artigos de encomenda por ID de encomenda e clientes por região. Estas chaves suportam os padrões operacionais de acesso da aplicação, mas um relatório de vendas agrupado por produto deve ler os dados entre partições e combiná-los no código da aplicação.

A figura seguinte mostra uma vista materializada que armazena o valor total das vendas e o número de clientes compradores distintos para cada produto na categoria de Eletrónica. As linhas de origem e os valores de resumo são ilustrativos, não um conjunto de dados de entrada completo para os totais apresentados.

Diagrama que mostra as tabelas Encomenda, Item da Encomenda e Cliente combinadas num sumário de vendas materializado, particionado por categoria de produto.

Um processo em segundo plano lê as entidades de origem necessárias, associa os artigos encomendados às suas encomendas e clientes, e agrega as vendas por produto. Conta cada cliente uma vez por produto, mesmo quando esse cliente tem várias encomendas ou linhas de encomendas. O processo escreve os resultados numa tabela resumida separada com a categoria do produto como PartitionKey e o ID do produto como RowKey. Esta tabela resumida é uma projeção mantida pela aplicação, não uma vista materializada nativa da base de dados.

Um dashboard pode então consultar a partição Eletrónica em vez de repetir as leituras e agregação cruzadas para cada pedido. Uma pesquisa por um produto fornece ambas as chaves. Para as implicações destas chaves no desempenho das consultas, consulte Design for querying.

Atualize o resumo num calendário que cumpra a janela de estagnação aceitável do relatório. Construa e valide uma nova versão antes de a publicar, para que os leitores continuem a usar a versão completa anterior durante uma reconstrução. A atualização continua a gerar custos de leitura e agregação entre partições, mas consultas repetidas ao relatório reutilizam o resultado. As alterações à fonte só são visíveis quando uma atualização subsequente as incluir.

Passos seguintes

Os padrões a seguir também podem ser relevantes quando você implementa esse padrão:

  • Padrão de Segregação das Responsabilidades de Comando e de Consulta (CQRS). Utilize esta opção para atualizar as informações numa vista materializada ao responder a eventos que ocorrem quando os valores dos dados subjacentes são alterados.
  • Padrão de Event Sourcing. Use juntamente com o padrão CQRS para manter a informação numa visão materializada. Quando os valores dos dados em que uma vista materializada se baseia são alterados, o sistema pode gerar eventos que descrevem essas alterações e guardá-los num armazenamento de eventos.
  • Padrão de Tabela de Índice. Por norma, os dados numa vista materializada estão organizados por uma chave primária, mas as consultas podem ter de obter informações a partir desta vista ao examinar os dados noutros campos. Use este padrão para criar índices secundários em vez de conjuntos de dados para repositórios de dados que não suportam índices secundários nativos.