stat_dump

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

Функция dump_statistic выдает операторы INSERT, которые затем можно применить к совместимой базе данных. Чтобы успешно восстановить статистические данные, это расширение следует установить и на исходном, и на целевом сервере, так как эти операторы будут задействовать функции, реализованные в расширении.

ВНИМАНИЕ!
Определение таблицы pg_statistic может поменяться в новых версиях, в результате чего старые экспорты могут оказаться несовместимыми.



Установка

CREATE EXTENSION stat_dump;


Функции

Основные

dump_statistic() returns setof text

Выгружает содержимое системного каталога pg_statistic, выдавая INSERT для каждого кортежа в pg_statistic, кроме тех, что содержат статистические данные о таблицах в схемах information_schema и pg_catalog.

Оператор INSERT принимает следующую форму:

WITH upsert as (
  UPDATE pg_catalog.pg_statistic SET [имя_столбца1 = значение1, ...]
  WHERE starelid = '{t_relname}'::regclass
    AND to_attname('{t_relname}'::regclass, staattnum) = '{t_attname}'
    AND to_atttype('{t_relname}'::regclass, staattnum) = '{t_atttype}'
    AND stainherit = {t_stainherit}
  RETURNING *),
ins as (
  SELECT [значение1, ...]
  WHERE NOT EXISTS (SELECT * FROM upsert)
    AND to_attnum('{t_relname}', '{t_attname}') IS NOT NULL
    AND to_atttype('{t_relname}'::regclass, '{t_attname}') = '{t_atttype}')
INSERT INTO pg_catalog.pg_statistic SELECT * FROM ins;

/*
     где значениеN может быть представлено в одном из следующих вариантов:
     - значение::имя_типа
     - array_in(текст_массива, имя_типа::regtype::oid, -1)

     а вместо t_relname, t_attname и t_atttype подставляются конкретные
     значения
*/

Для сохранения выданных операторов, необходимо направить вывод psql в файл, используя стандартные возможности psql. Например, чтобы сохранить статистику базы данных имя_базы в файл dump_stat.sql, надо выполнить:

psql -XAtq -c "SELECT dump_statistic()" имя_базы > dump_stat.sql

Вспомогательные

to_schema_qualified_type(id_типа oid) returns text

Выдает дополненное схемой имя типа по заданному id_типа.

to_schema_qualified_relation(id_отношения oid) returns text

Выдает дополненное схемой имя отношения по заданному id_отношения.

to_attname(отношение regclass, номер_столбца int2) returns text

Для заданных отношения и номера_столбца возвращает имя столбца в виде значения text.

to_attnum(отношение regclass, столбец text) returns int2

Для заданных отношения и столбца возвращает номер столбца в виде значения int2.

to_atttype(отношение regclass, столбец text) returns text

Для заданных отношения и столбца возвращает дополненное схемой имя типа столбца в виде значения text.

to_atttype(отношение regclass, номер_столбца int2) returns text

Для заданных отношения и номера_столбца возвращает дополненное схемой имя типа столбца в виде значения text.



Ограничения

Нельзя экспортировать отдельно: схемы, схемы и таблицы, отношения.

Расширение не совместимо с параметром qss_encrypt_statistic (не работает и экспорт и импорт). Экспорт статистики считается небезопасным при включенном шифровании.



Заметки по реализации

  • В UPDATE и INSERT значениеN — это непосредственные значения, которые вставляются в таблицу pg_statistic. В UPDATE и INSERT они одинаковы, то есть дублируют друг друга (за исключением того что в UPDATE форма записи "имя = значение", а в INSERT просто "значение"), в связи с тем, что решение о том, произойдет ли UPDATE или INSERT, принимается во время импорта, а не экспорта.
  • Функции to_attname, to_atttype и to_attnum используются для исключения использования идентификаторов таблиц и полей, так как они могут отличаться в базе, в которую производится импорт. Таким образом, эти функции принимают человеко-читаемое имя и конвертируют его в OID'ы текущего экземпляра.
  • Логика использования UPDATE и INSERT состоит в том, что сначала выполняется попытка сделать UPDATE, если статистика для соответствующих строк уже существует в pg_statistic, иначе делается INSERT.
  • Функция array_in создает значение типа anyarray, принимая на вход строку определенного формата (например, '{1,2,3}') и тип элементов массива. Пример: select array_in('{1,2,3}', 'int4'::regtype, -1);.