Делает ли SELECT FOR UPDATE в PostgreSQL копирование записи в блоке данных?
Известно, что PostgreSQL внутренне не обновляет записи -- при обновлении какой-либо записи просто предыдущая версия помечается устаревшей и в блок данных добавляется копия этой записи. При этом записей в блоке ограничено размером этого блока, а старые записи удаляются только VACUUM-ом. Если блок переполняется, то нужно писать в новый, а это потеря производительности, и/или еще какие-то минусы.
Теперь предположим, что у нас есть большая таблица (сотня полей), при этом в ней активно обновляются (с каждым бизнес-запросом) только десяток полей, а остальные -- это в сущности всякие подстроечные параметры. Например, в таблице есть поле со временем последнего запроса из внешней системы.
Архитектура PostgreSQL приведет к тому, что на каждую транзакцию обновления будет копироваться 90% не меняющихся полей в таблице ради того, чтобы записать оставшиеся 10%. Это приведет к быстрому распуханию файлов данных.
Таким образом, принято решение разделить таблицу на две, с часто и с редко меняющимися данными. И тут возникает вопрос.
Приложение в своей работе использует SELECT FOR UPDATE
на этой таблице, чтобы бизнес-запросы сериализовались в правильном порядке. Когда мы разделим таблицу на две, то SELECT FOR UPDATE
будет делаться только для одной из таблиц (это делает ORM, на который не повлиять, вторая таблица все равно не будет использоваться без первой), и тут возникает вопрос, а чем является этот SELECT FOR UPDATE
? Является ли он той записью (write), которая приводит к дублированию записи (row/record) в файлах данных или нет?
Документация для SELECT FOR UPDATE направляет на документацию по блокировкам, где сказано следующее
PostgreSQL doesn't remember any information about modified rows in memory, so there is no limit on the number of rows locked at one time. However, locking a row might cause a disk write, e.g.,
SELECT FOR UPDATE
modifies selected rows to mark them locked, and so will result in disk writes.
Означает ли выделенное то самое копирование строчки (row/record) в блоке данных? Иными словами, ради того, чтобы разделение большой таблицы имело задуманный смысл, нужно ли делать SELECT FOR UPDATE
для таблицы с меньшим числом полей (оперативные данные), или такая оптимизация также сработает, если будет делаться для таблицы с большим числом полей (настроечные данные)?