Шаблон материализованного представления

Создайте предварительно заполненные представления по данным в одном или нескольких хранилищах данных, если данные не идеально форматируются для необходимых операций запроса. Этот подход может поддерживать эффективное извлечение запросов и извлечение данных и повысить производительность приложения.

Контекст и проблема

При хранении данных разработчики и администраторы данных часто определяют, как хранятся данные, а не как они считываются. Выбранный формат хранилища обычно отражает формат данных, требования к управлению размером данных и целостностью данных, а также типом используемого хранилища. Например, при использовании хранилища документов NoSQL часто представляются данные в виде ряда агрегатов, каждая из которых содержит всю информацию для этой сущности.

Однако этот подход может негативно повлиять на запросы. Если для запроса требуется только подмножество данных из нескольких объектов, например сводка о заказах нескольких клиентов без подробностей о самом заказе, чтобы получить необходимую информацию, запросу необходимо извлечь все данные для соответствующих объектов.

Добавление индексов или изменение запросов во время чтения не всегда устраняет эту неэффективность. Многие хранилища нельзя переиндексировать для произвольных схем чтения без ущерба для производительности записи. Агрегирование по нескольким сущностям по-прежнему требует больших затрат ресурсов при выполнении запроса. Некоторые магазины по замыслу поддерживают лишь ограниченные возможности запросов. Из-за этих ограничений оптимизация пути чтения в исходном хранилище часто недостаточно.

Решение

Для обеспечения эффективного выполнения запросов обычно заранее создают материализованное представление данных в формате, подходящем для требуемого результирующего набора. Шаблон материализованного представления описывает создание заполненных представлений данных в тех случаях, когда формат исходных данных не подходит для запросов, когда сложно создать подходящий запрос или в случае низкой производительности запроса из-за типа данных или хранилища данных.

В этом шаблоне материализованное представление — это модель чтения или проекция, которая сохраняет данные, производные от одного или нескольких исходных хранилищ. Выделенный компонент приложения или конвейер данных может поддерживать проекцию, включая границы хранилища. Потребители запросов рассматривают проекцию как доступную только для чтения. Эта архитектура более широка, чем объект с материализованным представлением базы данных, который ядро СУБД определяет, хранит и обновляется в соответствии с собственными ограничениями функций.

Эти материализованные представления, содержащие только данные, необходимые запросу, позволяют приложениям быстро получать необходимые сведения. Помимо соединения таблиц или объединения сущностей данных, материализованные представления могут включать текущие значения вычисляемых столбцов или элементов данных, результаты объединения значений или преобразования элементов данных, а также значения, указанные как часть запроса. Материализованное представление может быть оптимизировано даже для одного запроса.

Ключевой момент заключается в том, что материализованное представление и содержащиеся в нём данные можно полностью отбросить, поскольку они могут быть целиком воссозданы на основе исходных хранилищ данных. Потребители запросов не обновляют представление напрямую. Вместо этого выделенный компонент, конвейер данных или ядро СУБД поддерживает его, поэтому это специализированный кэш.

Когда исходные данные для представления изменяются, представление должно обновиться, чтобы включить новые сведения. Вы можете запланировать это обновление автоматически или когда система обнаруживает изменение исходных данных. В некоторых случаях может потребоваться повторно создать представление вручную. На следующем рисунке показан пример использования шаблона материализованного представления.

Схема, показывающая пример использования шаблона материализованного представления.

Проблемы и рекомендации

При принятии решения о том, как реализовать этот шаблон, учитывайте следующие моменты:

  • Просмотреть стратегию обновления В идеале представление повторно создается в ответ на событие, указывающее на изменение исходных данных, хотя этот подход может привести к чрезмерной нагрузке, если исходные данные быстро изменяются. Кроме того, для повторного создания представления можно использовать запланированную задачу, внешний триггер или сделать это вручную.

  • Поведение при обновлении Определите, выполняет ли реализация полную пересборку или применяет изменения инкрементально. Кроме того, необходимо решить, должны ли операции обновления блокировать операции чтения.

    Эти решения определяют, возвращают ли запросы потенциально устаревшие материализованные данные, объединяют материализованные данные с необработанные изменения источника для возврата текущих результатов или продолжают обслуживать последнюю полную версию до завершения обновления.

  • Обновление надежности сигнала. Если сигнал активации, который запускает повторную генерацию представления, теряется или задерживается — например, из-за пропущенного события в ленте изменений или сбоя запланированной задачи, — представление молча возвращает устаревшие результаты. Отслеживайте давность обновления и отправляйте оповещение, когда время с момента обновления представления превышает допустимый интервал устаревания.

  • Обновить стоимость вычислительных ресурсов. Повторное создание представления использует вычислительные ресурсы пропорционально объему исходных данных и сложности преобразований. Для обновления на основе событий при быстром изменении исходных данных или для полного перестроения больших аналитических представлений вычислительные затраты могут быть значительным драйвером затрат. Оптимально подберите частоту и охват обновления, чтобы сбалансировать актуальность данных и затраты на вычислительные ресурсы.

  • Зависимость от источника событий. В некоторых системах, например при использовании шаблона "Источник событий " для хранения только событий, изменяющих данные, материализованные представления обычно необходимы. Предварительное заполнение представлений путем проверки всех событий для определения текущего состояния может быть единственным способом получить данные из хранилища событий. Если вы не используете паттерн Event Sourcing, подумайте, будет ли полезно материализованное представление. Материализованные представления, как правило, специально адаптированы к одному или небольшому количеству запросов. При использовании большого количества запросов материализованные представления могут привести к неприемлемым требованиям к емкости хранилища и затратам на него.

  • Согласованность данных. Учитывайте влияние на согласованность данных при создании представления и при обновлении представления, если этот процесс происходит по расписанию. Если исходные данные изменяются одновременно с созданием представления, копия данных в представлении не полностью согласуется с исходными данными. Максимальное время ожидания является прямым следствием интервала обновления или задержки обработки событий, поэтому определите допустимое устаревание перед выбором между событиями, запланированным или ручным обновлением.

  • Просмотр расположения хранилища. Представление не обязано находиться в том же хранилище или разделе, что и исходные данные. Вы можете объединить подмножества из нескольких разных разделов.

  • Перестроение по потере. Представление можно пересоздать в случае его утраты. Таким образом, если представление является временным и используется только для повышения производительности запросов, отражая текущее состояние данных или повышая масштабируемость, его можно хранить в кэше или в менее надежном расположении.

    Однако если сам процесс обновления завершается сбоем ( например, если запланированная задача повторного восстановления завершается сбоем), определите, должна ли рабочая нагрузка обслуживать предыдущее полное представление, частично обновленное представление или представление вообще, пока восстановление не завершится успешно.

    Самый безопасный подход, как правило, заключается в атомарной публикации или замене с использованием версий, при которой система продолжает обслуживать запросы и использовать последнюю полностью сформированную версию представления, пока вы создаёте и проверяете новое представление. Переключение на новое представление после завершения проверки.

  • Вычисляемые столбцы. При определении материализованного представления максимально увеличить его значение путем добавления элементов данных или столбцов на основе вычислений или преобразования существующих элементов данных, значений, передаваемых в запросе, или сочетаний этих значений при необходимости.

  • Просмотреть индексирование Если механизм хранилища поддерживает такую возможность, рекомендуется индексировать материализованное представление для еще большего повышения производительности. Многие реляционные базы данных поддерживают индексацию представлений. Однако поддержание индекса для представления добавляет дополнительные накладные расходы при записи в каждом цикле обновления, поэтому соотносите выигрыш в производительности чтения с дополнительным временем обновления и вычислительными затратами.

  • Управление доступом к представлениям. Если материализованное представление используется для ограничения того, какие подмножества данных видны определенным потребителям, например по соображениям безопасности или конфиденциальности, хранилище представлений должно применять те же или более строгие элементы управления доступом, что и исходные данные. Конвейер обновления должен исключить непреднамеренные столбцы или строки, так как представление, которое случайно включает данные за пределы предполагаемой области, может предоставлять защищенные данные.

  • Жизненный цикл данных в представлениях. Примените требования к хранению и удалению исходных данных к каждому материализованному представлению. Распространять удаления из источника и редакции в течение требуемого периода, а также включать каждое представление в мониторинг соответствия требованиям. Дополнительные сведения см. в разделе "Управление данными" и базовые показатели безопасности с Microsoft Purview.

  • Просмотреть управление жизненным циклом Рассматривайте определения представлений как развертываемые артефакты, которыми управляют через систему контроля версий и конвейеры CI/CD, особенно если представления определяются декларативно. Без управления жизненным циклом определения представлений могут дрейфовать между средами, вызывая несогласованность поведения запросов между разработкой, промежуточной и рабочей средой.

Когда следует использовать этот шаблон

Используйте этот шаблон, когда:

  • Необходимо создать представления по данным, которые трудно запрашивать напрямую или где запросы должны быть очень сложными для извлечения данных, хранящихся в нормализованном, полуструктурированном или неструктурированном способе.
  • Вы хотите создать пересоздаваемые или временные кэшированные проекции, которые повышают производительность запросов или формируют данные, используемые для создания объектов передачи данных для пользовательского интерфейса, отчета или экрана.
  • Иногда требуется поддержка сценариев подключения или отключения, когда подключение к хранилищу данных не всегда доступно. В этом случае можно кэшировать представление локально.
  • Вы хотите упростить запросы и предоставить данные для экспериментирования таким образом, что не требует знания о формате исходных данных. Например, это делается путем объединения разных таблиц в одну или несколько баз данных либо одного или нескольких доменов в хранилищах NoSQL и последующего форматирования данных в соответствии со способом использования.
  • Вы хотите предоставить доступ к определенным подмножествам исходных данных, которые, по соображениям безопасности или конфиденциальности, не должны быть общедоступными, открытыми для изменения или полностью предоставляемыми пользователями.
  • Вы хотите мостить различные хранилища данных, чтобы воспользоваться преимуществами их отдельных возможностей. Например, можно использовать облачное хранилище, эффективное для записи в качестве эталонного хранилища данных, а реляционную базу данных, которая обеспечивает хорошую производительность запросов и чтения для хранения материализованных представлений.
  • Если вы используете микросервисы, обеспечьте их слабую связанность, включая хранилища данных. Материализованные представления могут помочь объединить данные из ваших сервисов. Если материализованные представления не подходят для архитектуры микрослужб или конкретного сценария, рассмотрите возможность четко определенных границ, которые соответствуют дизайну на основе домена (DDD) и агрегируют свои данные по требованию.

Этот шаблон может быть не подходит, если:

  • Используются простые исходные данные, для которых легко создавать запросы.
  • Исходные данные меняются очень быстро или доступ к ним можно осуществлять без использования представления. В этих случаях избегайте дополнительных затрат на обработку при создании представлений.
  • Согласованность имеет высокий приоритет. Представления могут быть не всегда полностью согласованными с исходными данными.

Проектирование рабочей нагрузки

Архитектор должен оценить, как шаблон материализованного представления можно использовать в проектировании рабочей нагрузки для решения целей и принципов, описанных в основных принципах Платформы Azure Well-Architected Framework. Рассмотрим пример.

Столп Как этот шаблон поддерживает цели основных компонентов
Эффективность производительности помогает рабочей нагрузке эффективно соответствовать требованиям путем оптимизации масштабирования, данных и кода. Материализованные представления хранят результаты сложных вычислений или запросов, не требуя повторной компиляции ядра СУБД или клиента для каждого запроса. Эта конструкция снижает общее потребление ресурсов.

- PE:08 Производительность данных

Если этот шаблон вводит компромиссы внутри столпа, рассмотрите их против целей других столпов.

Example

Рассмотрим приложение для продаж, которое хранит сущности Order, OrderItem и Customer в Azure Table Storage. Заказы секционируются по идентификатору клиента, элементам заказа по идентификатору заказа и клиентам по регионам. Эти ключи поддерживают шаблоны рабочего доступа приложения, но отчет о продажах, сгруппированных по продукту, должен считывать данные между секциями и объединять его в код приложения.

На следующем рисунке показано материализованное представление, в котором хранятся общая сумма продаж и количество уникальных клиентов, совершивших покупку, для каждого товара в категории Электроника. Исходные строки и сводные значения приведены в качестве иллюстрации, а не как полный входной набор данных для показанных итогов.

Схема, показывающая таблицы Order, OrderItem и Customer, объединенные в материализованную сводку по продажам, секционированную по категориям продуктов.

Фоновый процесс считывает необходимые исходные объекты, связывает позиции заказа с соответствующими заказами и клиентами, а также агрегирует продажи по продуктам. Он подсчитывает каждого клиента один раз на продукт, даже если у этого клиента несколько заказов или линий заказов. Процесс записывает результаты в отдельную сводную таблицу с категорией продукта как PartitionKey и идентификатором RowKeyпродукта. Эта сводная таблица представляет собой проекцию, поддерживаемую приложением, а не материализованное представление, встроенное в СУБД.

После этого панель мониторинга может выполнять запросы к разделу Electronics вместо того, чтобы для каждого запроса повторно выполнять чтение из разных разделов и агрегацию данных. Поиск одного продукта предоставляет оба ключа. Сведения о влиянии на производительность запросов этих ключей см. в разделе "Проектирование запросов".

Обновляйте сводку по расписанию, соответствующему допустимому интервалу устаревания отчёта. Создайте и проверьте новую версию перед публикацией, поэтому читатели продолжают использовать предыдущую полную версию во время перестроения. Обновление по-прежнему сопровождается затратами на чтение из разных разделов и на агрегирование, но повторные запросы к отчету используют уже полученный результат. Изменения в исходных данных не будут видны, пока последующее обновление не включит их.

Дальнейшие действия

При реализации этого шаблона могут быть также важны следующие шаблоны:

  • Шаблон разделения ответственности команд и запросов (CQRS). Используйте для обновления сведений в материализованном представлении в ответ на события, возникающие при изменении значений данных.
  • Шаблон источников событий. Используйте вместе с паттерном CQRS для поддержания информации в материализованном представлении. Если данные значения материализованного представления основаны на изменении, система может вызывать события, описывающие эти изменения и сохраняющие их в хранилище событий.
  • Шаблон таблицы индексов. Данные в материализованном представлении обычно организованы по первичному ключу, но для выполнения запросов может понадобиться получение сведений из этого представления путем проверки данных в других полях. Используйте этот шаблон для создания вторичных индексов над наборами данных для хранилищ данных, которые не поддерживают собственные вторичные индексы.