Привет, это Павел Селезнев, участник команды Pangolin. Пару недель назад я выступил на ... — 7 апреля 2026 г. в 07:41:18.936
Привет, это Павел Селезнев, участник команды Pangolin. Пару недель назад я выступил на PG BootCamp с докладом «Временные таблицы для PostgreSQL. Почему это важно для платформы 1С и что можно улучшить?». ⏯️ Запись доклада можно посмотреть по ссылке После выступления мне задали несколько интересных вопросов. Сегодня разберу вопрос о медленной работе оператора UPDATE. Спасибо автору за вопрос и за то, что позже прислал почтой дополнительные детали 👍 ➡️ Схема базы данных Таблица cmn_object (назовем её «Справочник идентификаторов») CREATE TABLE cmn_object ( id bigint PRIMARY KEY ); Таблица od_structure_extension (назовем её «Справочником апартаментов») CREATE TABLE od_structure_extension ( id bigint PRIMARY KEY, object_id bigint , common_apartment_number int NOT NULL ); Таблица _result (назовем её «Доступными апартаментами») CREATE TEMP TABLE _result ( identity_column bigint NOT NULL, object_id bigint NOT NULL, living_rooms_amount varchar(30) ) ➡️ Проблемный запрос ----------------- Задача: требуется обновить те апартаменты, которые есть в _result и не заняты. UPDATE _result r_u SET living_rooms_amount = ex.common_apartment_number::varchar FROM _result r JOIN cmn_object o ON r.object_id = o.id JOIN no.od_structure_extension ex ON ex.object_id = o.id WHERE r_u.identity_column = r.identity_column AND r.living_rooms_amount IS NULL; Проблема: запрос выполняется очень медленно. Уточним, что: 1) Проблема не относится к временным таблицам, если мы уберём ключевое слово TEMP, то она сохранится 2) Оптимизатор ошибается со статистикой, т.к. она не актуальна. Поэтому в начале здесь у нас происходит self join (то есть декартово произведение таблицы саму на себя), и далее идёт фильтрация миллионов строк. ✔️ Возможные решения 1) Можно переписать запрос так: UPDATE _result u SET living_rooms_amount = ( SELECT ex.common_apartment_number::varchar FROM no.cmn_object o JOIN no.od_structure_extension ex ON ex.object_id = o.id WHERE o.id = u.object_id LIMIT 1 ) WHERE u.living_rooms_amount IS NULL AND EXISTS ( SELECT 1 FROM no.cmn_object o JOIN no.od_structure_extension ex ON ex.object_id = o.id WHERE o.id = u.object_id ); 2) Если запрос редко выполняется, то можно запустить Analyze перед ним.

