TL;DR: запрос материализованных представлений, в отличие от запроса таблиц или логических представлений, может снизить затраты на запрос, сохраняя результаты в памяти, которые обновляются только при необходимости. Чтобы узнать больше, ознакомьтесь с остальной частью поста!
Стоимость запроса
Каждый раз, когда вы запрашиваете базу данных, вы несете определенные затраты. Ваша база данных будет анализировать, проверять, планировать, оптимизировать и выполнять ваш запрос, используя время настенных часов, процессорное время, память, альтернативные издержки и, возможно, фактические доллары. По мере роста вашего приложения вы, вероятно, будете задаваться вопросом, как вы можете сократить эти расходы.
Чтобы разобраться в этом, давайте рассмотрим пример. Представьте, что вы работаете в компании, которая продает виджеты. Каждый раз, когда виджет продается, вы записываете некоторую информацию о покупке в таблицу покупок, которая выглядит следующим образом:
С помощью этих данных вы можете ответить на вопросы, которые имеют решающее значение для вашего бизнеса: какой наш самый продаваемый виджет? Какие виджеты нужно отправить сегодня? И вечнозеленый вопрос: сколько денег мы заработали?
На каждый из этих вопросов можно ответить, обратившись непосредственно к таблице покупок. Например, вы можете рассчитать свой общий доход с помощью следующего запроса:
Когда этот запрос будет запущен, ваша база данных будет сканировать каждую строку таблицы покупок, чтобы агрегировать значения в столбце сумма. Ваша база данных потратит X ресурсов, чтобы вернуть ваш результат. (Как упоминалось ранее, X состоит из времени настенных часов, процессорного времени, памяти, альтернативных издержек и долларов.)
Хорошая новость заключается в том, что вы с удовольствием платите X, потому что эта информация важна и ценна для вашего бизнеса. Плохая новость заключается в том, что вы будете платить X при каждом запуске вашего запроса. Поскольку запросы к таблицам и представлениям не ссылаются на предыдущие результаты, они вынуждены каждый раз полностью пересчитывать свои результаты.
Возможно, вы зададитесь вопросом: А разве это так важно? Если ваш запрос является исследовательским, нерегулярным или нечастым, скорее всего, это не так. Но что, если вам вдруг понадобится подсчитывать общий доход раз в час, а не раз в день? Или раз в секунду?
Внезапно даже маленький крестик начинает казаться дорогим. Поскольку ваши запросы выполняются чаще, обрабатывают больше данных или выполняют более сложные вычисления, эти затраты могут даже показаться непомерно высокими. Итак, что вы можете сделать вместо этого?
Материализованные Представления
В отличие от запросов, которые вычисляют свои результаты из таблиц и представлений, запросы, считывающие данные из материализованных представлений, не пересчитывают свои результаты каждый раз. Чтобы понять почему, давайте вместе создадим материализованное представление.
Когда этот оператор будет выполнен, ваша база данных выполнит ваш запрос один раз, чтобы вычислить результат. Затем он физически сохранит этот результат во вновь созданном объекте базы данных — в нашем случае объекте с именем total_revenue. Теперь, когда вы запрашиваете total_revenue, ваша база данных возвращает результаты, хранящиеся в total_revenue, без выполнения каких-либо дополнительных вычислений.
Это означает, что в отличие от прямого запроса представления, вы оплачиваете стоимость запроса только один раз при создании материализованного представления.* Будущие запросы будут платить некоторую постоянную стоимость 1 для чтения из total_revenue вместо X.
Это кажется идеальным решением нашей проблемы, так в чем же подвох? Почему мы не используем материализованные представления для всего?
Два Улова*
Первая загвоздка заключается в том, что вы платите за материализованные представления памятью. Хотя материализованные представления, физически хранящие предыдущие результаты, снижают стоимость запроса с X до 1, они также требуют памяти, которая не требовалась для простого запроса таблицы или логического представления.
Второй, более сложный улов появляется, когда новая покупка добавляется в таблицу покупок. Чтобы проиллюстрировать это, давайте вместе пройдемся по этому сценарию.
Заметив, что у нас есть новая продажа в нашей таблице покупок, мы запрашиваем наше материализованное представление для нашего обновленного общего дохода. Но мы возвращаем себе нашу прежнюю ценность. Что дает?
Когда мы создали наше материализованное представление, наша база данных выполнила наш запрос один раз, чтобы сохранить результаты в total_revenue. Однако, поскольку запрос был выполнен до того, как новая покупка была добавлена в таблицу покупок, результат, вычисленный и сохраненный в total_revenue, не учитывает эту новую покупку. Чтобы обновить результат и включить в него новые покупки, вам придется обновить материализованное представление. Как правило, существует два механизма обновления материализованных представлений: полное обновление или постепенное обновление.
Полное обновление повторяет запрос, лежащий в основе материализованного представления, чтобы полностью пересчитать и заменить сохраненные результаты. Как и запросы к таблицам и представлениям, каждое полное обновление будет стоить X. Чтобы усложнить ситуацию, вам придется решить, когда выполнять обновление: когда кто-то запрашивает представление? Раз в час? Раз в неделю? Вы захотите выбрать каденцию, которая не заставит базу данных выполнять ненужную работу. Например, вы не хотите платить X recompute total_revenue, если нет новых покупок. В реальных системах пользователям придется выбирать расписание обновления, которое поддерживает тщательный баланс между требованиями к свежести данных и приемлемыми затратами на запросы.
Напротив, инкрементные обновления поддерживают материализованные представления в актуальном состоянии, выполняя работу только с измененными данными. Чтобы вернуться к нашему примеру, вместо повторного сканирования каждой строки таблицы покупок для вычисления суммы, постепенно поддерживаемое материализованное представление будет выполнять только следующую работу:
Это означает, что вместо того, чтобы платить X за обновление представления, ваша база данных будет платить только часть X, пропорциональную размеру измененных данных. И поскольку этот механизм обновления запускается изменениями в базовых данных, вы можете быть уверены, что ваша база данных обновляет ваше представление не больше, чем это необходимо. В нашем примере total_revenue будет обновляться только при вставке, обновлении или удалении строки в таблице покупок.
Заключение
Создание и поддержание материализованного представления может снизить затраты на запросы, оплачиваемые за дорогостоящие или часто выполняемые запросы. Однако потенциальное снижение стоимости материализованного представления в значительной степени зависит от лежащего в его основе механизма обновления. Только инкрементное обновление может снизить затраты на поддержание материализованного представления за одно обновление, а также гарантировать, что представления обновляются не чаще, чем это необходимо.
Хотя инкрементные обновления доступны в нескольких базах данных, они часто сопровождаются длинным списком ограничений. На данный момент Materialize-это единственная система, которая поддерживает инкрементные поддерживаемые материализованные представления без ограничений. Если вы идентифицировали себя с болевыми точками в этом блоге, проверьте нас!
https://materialize.com/why-use-a-materialized-view/