Postgres: более быстрые проверки внешних ключей
Автор: Amit Langote, Postgres: faster foreign key checks
В одной из предыдущих статей я описывал, как работает обеспечение целостности внешних ключей в Postgres. Краткая версия такова: каждая команда INSERT или UPDATE в таблицу, ссылающуюся на другую, запускает триггер AFTER, который проверяет, существуют ли значения столбца внешнего ключа (FK) в ссылочной (PK) таблице. Эта проверка проходит через SPI (Server Programming Interface): строится запрос, он планируется, выполняется, а затем всё уничтожается — для каждой отдельной строки.
Это дорогостоящая операция. При массовой вставке (INSERT) миллиона строк в таблицу с внешним ключом вы выполняете миллион мини-запросов к индексу таблицы первичного ключа. Каждый из них открывает отношение первичного ключа, захватывает снимок (snapshot), выполняет проверку прав, делает поиск по индексу и закрывает всё. Стоимость одной строки в абсолютном выражении невелика, но она очень быстро накапливается.
Для Postgres 19 я применил два патча (соавтором обоих является Джунванг Жао), которые полностью обходят SPI для стандартного случая и выполняют пакетную (batch) проверку индекса. Вместе они ускоряют массовые вставки с внешними ключами примерно в 2.9 раза в используемом мною тесте (int первичный ключ, int внешний ключ, 1 миллион строк, таблица первичного ключа и её индекс в памяти).