awesome-everything EN
↑ Обратно к восхождению

Data engineering

Materialized views: чтение SQL и refresh

Суть Читайте реальный SQL — настройку REFRESH CONCURRENTLY, создание immv через pg_ivm и проверку окна staleness — и выбирайте поведение или фикс с наибольшим рычагом, который сделает senior.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min

Сам оператор refresh и SQL вокруг него — там, где рождаются проблемы materialized view. Читайте каждый сниппет, предсказывайте, что сделает база, затем выбирайте фикс, к которому senior тянется первым.

Цель

Отработайте цикл, который вы запускаете при ревью MV: читайте DDL и путь refresh, предсказывайте поведение блокировок и staleness, и тянитесь к структурному фиксу раньше, чем к ручке тюнинга.

Сниппет 1 — предусловие CONCURRENTLY

CREATE MATERIALIZED VIEW daily_revenue AS
SELECT date_trunc('day', created_at) AS day,
       region,
       sum(amount) AS revenue
FROM orders
GROUP BY 1, 2;

-- ночная задача:
REFRESH MATERIALIZED VIEW CONCURRENTLY daily_revenue;
Викторина

Ночная задача сразу падает с ошибкой 'cannot refresh materialized view concurrently' / ошибкой уникального индекса. Чего не хватает и каким именно оно должно быть?

Сниппет 2 — incremental maintenance через pg_ivm

CREATE EXTENSION IF NOT EXISTS pg_ivm;

-- превращаем агрегат в инкрементально поддерживаемое представление
SELECT create_immv('daily_revenue_ivm',
  $$ SELECT date_trunc('day', created_at) AS day,
            region,
            sum(amount) AS revenue
     FROM orders
     GROUP BY 1, 2 $$);
Викторина

После create_immv коллега замечает, что каждый INSERT в orders стал ощутимо медленнее. Это баг и что происходит?

Сниппет 3 — обнаружение staleness

-- ops хочет алерт, если MV давно не обновлялся.
-- они запрашивают данные самого view на свежий день:
SELECT max(day) AS newest_day FROM daily_revenue;
-- алерт срабатывает, только если newest_day < current_date;
Викторина

Почему алерт на max(day) внутри view — ненадёжная проверка staleness, и что отслеживать вместо этого?

Сниппет 4 — refresh, который не завершается

-- открыта долгая аналитическая сессия:
BEGIN;
SELECT ... FROM orders JOIN ... ;   -- работает 20+ минут, всё ещё открыта

-- тем временем срабатывает планировщик:
REFRESH MATERIALIZED VIEW CONCURRENTLY daily_revenue;  -- как будто висит
Викторина

Refresh CONCURRENTLY стоит и ничего не делает, пока открыта аналитическая сессия. Каков механизм и каков надёжный фикс?

Итог

Путь refresh — там, где живут проблемы MV: CONCURRENTLY требует уникальный индекс на обычных колонках view, иначе падает; create_immv из pg_ivm переносит стоимость на каждую запись через триггеры, поэтому замедление записи — это дизайн, а не баг; staleness нужно измерять по успеху и таймстампу самой refresh-задачи, а не по содержимому данных view; а refresh CONCURRENTLY застревает за долгими открытыми транзакциями, поэтому ограничьте их, иначе он не догонит. Читайте DDL и refresh, предсказывайте поведение блокировок и staleness, затем чините структуру раньше, чем тянуться к ручке.

Продолжить восхождение ↑Materialized views: владей refresh
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.