Что могло go ошибаться при замене содержимого таблицы с использованием переименования таблицы в Postgresql? - PullRequest
1 голос
/ 08 мая 2020

Мне нужно атомарно изменить большое количество строк в таблице Postgresql. Я использую такую ​​технику: добавляю данные во временную таблицу, а затем меняю таблицы местами, переименовывая оригинал в not_matter_name и temp в исходное имя. Методика описана здесь .

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

Что еще, кроме проблемы с представлениями, могло go ошибиться с такой техникой?

Я что-то делаю не так? Есть ли лучшее решение для быстрой замены таблиц, которое не вызывает подобных побочных эффектов для других Postgresql сущностей?


Код выглядит так:

CREATE TABLE _temp_with_updated_data (like original_name including all);

--...MANY INSERTS TO _temp_with_updated_data

begin;
alter table original_name rename to ___doesnt_matter;
alter table _temp_with_updated_data rename to original_name;
alter table ___doesnt_matter to _temp_with_updated_data;
truncate table _temp_with_updated_data;
commit;

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Что еще, кроме проблемы с представлениями, могло go ошибиться с такой техникой?

  1. Любые другие зависимости объектов. Например,
    • Последовательности, «принадлежащие» таблице.
    • Публикации и подписки
    • Триггеры.
  2. Вы можете столкнуться с переходным процессом ошибки связь с oid XXX не существует .
  3. Если таблица секционирована / унаследована, подразделы тоже будут заблокированы.

Я бы серьезно подумал об использовании Шаблон DELETE / INSERT вместо шаблона RENAME / TRUNCATE.

Особенно, если ваши планы на будущее включают разбиение на разделы, логическую репликацию или репликацию на основе триггеров.

2 голосов
/ 08 мая 2020

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

Если вам не нравится воссоздавать представления, вы можете использовать наследование из пустой базы table и укажите на него взгляды. Тогда вы НЕ НАСЛЕДЕТЕ старую и НЕ НАСЛЕДУЙТЕ новую. Лично я считаю, что это лекарство хуже болезни, и просто воссоздаю взгляды. Вы можете получить определения представлений из pg_dump -s, если они еще не спрятаны в каком-то месте, но вам нужно самостоятельно разобраться, какие из них вам нужны.

Другая проблема может быть связана только с производительностью эта массовая вставка в уже проиндексированную таблицу может быть медленной. Вы можете создать с ВКЛЮЧЕНИЕМ ВСЕ ИСКЛЮЧАЮЩИЕ ИНДЕКСЫ, а затем построить индексы после заполнения. Увы, PostgreSQL не позволяет легко выполнить вторую часть. Нет ничего похожего на гипотетический ALTER TABLE foo2 INCLUDE INDEXES LIKE foo1, который вы можете запустить постфактум (но опять же, pg_dump -s может помочь здесь, чтобы получить список операторов создания индекса). Но если текущая производительность вас не беспокоит, просто не исключайте индексы в первую очередь, и вам не нужно будет создавать их позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...