Как стать автором
Обновить

Немного про SLA для DWH на PostgreSQL

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров4.2K

Описание проблемы

В некоторых случаях в DWH приходится периодическим заданием очищать таблицу и заполнять ее новыми актуальными данными. Например, раз в сутки. Если в таблице десятки или сотни тысяч строк, то это не проблема. А вот если миллиард - то уже точно проблема. Потому что каким бы способом ее не заполнять, но в течении достаточно длительного времени данные из этой таблицы не будут доступны пользователям. А если система должна быть доступна 24/7, то такие процессы начинают заметно ухудшать SLA.

Варианты решения

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

Второй вариант - через переименование таблиц. И именно он выглядит предпочтительней.

Описание решения

Нашу таблицу очищает и заполняет какая-то конкретная хранимая процедура. Назовем ее условно SomeScheme.ThisTablePeriodicFill_sp. Тогда у нас возникает логический ресурс to_regproc('SomeScheme.ThisTablePeriodicFill_sp')::oid::integer, который мы и будем использовать для логических блокировок. Перед доступом к нашей таблице каждый клиент должен выполнить:

PERFORM pg_advisory_lock_shared(
  to_regproc('SomeScheme.ThisTablePeriodicFill_sp')::oid::integer, 0);

А по окончании работы с нашей таблицей клиент должен освободить ресурс:

PERFORM pg_advisory_unlock_shared(
  to_regproc('SomeScheme.ThisTablePeriodicFill_sp')::oid::integer, 0);

Теперь процедура SomeScheme.ThisTablePeriodicFill_sp может создать новую таблицу SomeScheme.ThisTable_Shadow совпадающую по структуре с таблицей SomeScheme.ThisTable, но без индексов. После чего, никому не мешая, заполнить эту таблицу и, после ее заполнения, создать для нее необходимые индексы.

Однако просто переименовать эту таблицу мало. Ведь индексы в PostgreSQL являются relation и их имена глобальны. Для решения этой проблемы имена индексов делаем всегда начинающиеся с имени таблицы (например, ThisTable_IndexName_Idx) и создаем такую хранимую процедуру:

CREATE OR REPLACE PROCEDURE SomeSchema.normalize_index_names_sp (
  schema_name       varchar,
  table_name        varchar,
  from_index_prefix varchar ) AS $proc$
<<proc>>
DECLARE
  sql_str           varchar;
BEGIN
  SELECT string_agg('ALTER INDEX '
    ||schema_name||'.'||indexname||' RENAME TO '||LOWER(table_name)
    ||RIGHT(indexname,LENGTH(indexname)-LENGTH(from_index_prefix)),'; ')
  INTO sql_str
  FROM pg_catalog.pg_indexes
  WHERE schemaname=LOWER(schema_name) AND tablename=LOWER(table_name)
    AND indexname LIKE LOWER(from_index_prefix)||'%';
  EXECUTE sql_str;
END; $proc$ LANGUAGE plpgsql;

Используя данную процедуру мы получаем возможность быстро переименовать таблицы и их индексы:

PERFORM pg_advisory_lock(
  to_regproc('SomeScheme.ThisTablePeriodicFill_sp')::oid::integer, 0);
ALTER TABLE IF EXISTS SomeScheme.ThisTable RENAME TO ThisTable_Bak;
CALL SomeScheme.normalize_index_names_sp (
  'SomeScheme','ThisTable_Bak','ThisTable');
ALTER TABLE IF EXISTS SomeScheme.ThisTable_Shadow RENAME TO ThisTable;
CALL SomeScheme.normalize_index_names_sp (
  'SomeScheme','ThisTable','ThisTable_Shadow');
DROP TABLE IF EXISTS SomeScheme.ThisTable_Bak;
PERFORM pg_advisory_unlock(
  to_regproc('SomeScheme.ThisTablePeriodicFill_sp')::oid::integer, 0);

В данном коде опущен блок EXCEPTION, в котором при возникновении ошибок производится журналирование и попытка восстановить имя ThisTable.

Процесс переименования таблиц и их индексов в PostgreSQL выполняется очень быстро. Таким образом мы улучшаем SLA, сократив недоступность таблицы до времени ожидания в очереди, в худшем случае, на время логической блокировки (advisory_lock_shared) клиента, что намного меньше времени заполнения такой таблицы.

Теги:
Хабы:
Всего голосов 3: ↑3 и ↓0+3
Комментарии36

Публикации

Истории

Ближайшие события

Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
OTUS CONF: GameDev
Дата30 мая
Время19:00 – 20:30
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область