tl; dr: первый процесс, который считывает данные после его фиксации, устанавливает биты подсказок. Это испачкает страницу, создавая активность записи. Другая вещь VACUUM
(но не другие команды) помечает страницу как полностью видимую, если это необходимо. VACUUM
в конечном итоге придется ударить по столу, чтобы заморозить кортежи.
Работа, которая должна быть выполнена после вставки, на самом деле не очищается, по крайней мере, в отличие от VACUUM
обычной работы . Прежде чем углубляться в детали, обратите внимание, что этот ответ основан на текущем (неизданном) коде 9.6, и я игнорирую эффекты потоковой репликации, хотя это может повлиять на видимость.
Из-за MVCC каждый раз, когда Postgres оценивает, должен ли кортеж быть видимым для запроса, он должен учитывать, была ли зафиксирована транзакция, создавшая кортеж (записанный в скрытом поле xmin), а также некоторые другие критерии. Эта проверка является дорогой, поэтому, как только станет известно, что транзакция видима для всех открытых в настоящее время транзакций, в заголовке кортежа указывается «бит подсказки», указывающий на это. Установка этого бита загрязняет страницу, что означает, что она должна быть записана на диск. Это может быть очень запутанным, если следующая команда для чтения данных - это SELECT
внезапно создавшая большой трафик записи. Запуск VACUUM
после вставки фиксирует это. Другое важное отличие состоит в том, чтоVACUUM
ВСЕГДА будет подсказывать кортежи на странице (если она получила блокировку очистки на странице), но большинство других команд будут только подсказывать, если транзакция вставки зафиксирована до ее запуска.
Важным моментом при написании всех этих битов подсказок является то, что их VACUUM
можно регулировать (и по умолчанию регулируется автовакуум). Другие команды не регулируются и генерируют грязные данные как можно быстрее.
VACUUM
это единственный способ пометить страницы как полностью видимые, что является важным фактором производительности для некоторых операций (в частности, сканирование только по индексу). Если вы делаете большую вставку, очень вероятно, что есть много страниц с только что вставленными кортежами. VACUUM
потенциально может пометить эти страницы как полностью видимые, но только если самая старая запущенная транзакция при VACUUM
запуске была новее, чем транзакция, которая вставила данные .
Из-за того, как работает MVCC, кортежи, которые были вставлены более ~ 2 миллиардов транзакций назад, должны быть помечены как « замороженные ». По умолчанию включается автовакуум, чтобы делать это каждые 200 миллионов транзакций. Запуск ручного вакуума с вакуумом_свободной_мин_установки, установленным в 0 после массовой вставки, может помочь уменьшить влияние этого. Более агрессивно, вы можете бегать VACUUM FREEZE
по столу после вставки. Это «сбросит часы» при следующем сканировании.
Если вы хотите узнать конкретные детали, посмотрите на HEAPTUPLE_LIVE
случай после звонка HeapTupleSatisfiesVacuum()
внутрь lazy_scan_heap()
. Посмотри и HeapTupleSatisfiesVacuum()
сам, и сравни с ним HeapTupleSatisfiesMVCC()
.
Есть еще две мои презентации, которые могут быть интересными. Первое видео доступно с http://www.pgcon.org/2015/schedule/events/829.en.html , а второе (которое, я думаю, было немного лучше) на https://www.youtube. ком / часы? v = L8nErzxPJjQ
EXPLAIN (ANALYZE, BUFFERS) outputs. But, if I understand things correctly, some of the hint bits (at least
* COMMITTED` и*INVALID
) может (может) уже быть установленCOMMIT
илиROLLBACK
, верно?