tl; dr: Перший процес, який зчитує дані після їх введення, встановить біти підказки. Це забруднить сторінку, створивши активність у записі. Інша річ VACUUM(але не інші команди) - це позначати сторінку як усі видимі, якщо це доречно. VACUUMврешті-решт доведеться вдарити по столу, щоб заморозити кортежі.
Робота, яку потрібно виконати після вставки, насправді не є очищенням, принаймні, не в сенсі інших робіт, VACUUMяк правило. Перш ніж розібратися в деталях, зауважте, що ця відповідь заснована на поточному (неопублікованому) 9.6 коді, і я ігнорую ефекти потокової реплікації, хоча це може вплинути на видимість.
Через MVCC кожен раз, коли Postgres оцінює, чи повинен кордон бути видимим для запиту, він повинен враховувати, чи здійснена транзакція, яка створила кортеж (записаний у прихованому полі xmin), разом із деякими іншими критеріями. Цей чек коштує дорого, тому, як тільки стане відомо, що транзакція видна для всіх відкритих в даний час транзакцій, на заголовку кортежу встановлюється "біт підказки", що вказує на це. Налаштування цього біта забруднює сторінку, а значить, його доведеться записати на диск. Це може бути дуже заплутаним, якщо наступна команда для читання даних - SELECTце раптом створює багато трафіку запису. Запуск VACUUMпісля вставки вставить цього. Ще одна важлива відмінність полягає в тому, щоVACUUMЗАВЖДИ натякає кортежі на сторінку (доки вона заблокує очищення на сторінці), але більшість інших команд натякають лише у тому випадку, якщо трансакція вставки здійснена до початку команди.
Важливим моментом щодо написання всіх цих бітів підказки є те, що VACUUMможна заглушити (а автовакуум замовчується). Інші команди не утискаються і будуть генерувати брудні дані якомога швидше.
VACUUMце єдиний метод маркування сторінок як видимих, що є важливим врахуванням продуктивності деяких операцій (зокрема, індексувати лише сканування). Якщо ви робите велику вставку, велика ймовірність, що існує багато сторінок, окрім нещодавно вставлених кортежів. VACUUMможе потенційно позначити ці сторінки як усі видимі, але лише в тому випадку, якщо найстарша запущена транзакція при VACUUMзапуску була новішою, ніж транзакція, яка вставила дані .
Через те, як працює MVCC, кортежі, які були вставлені більше ~ 2 мільярдів транзакцій тому, повинні бути позначені як " заморожені ". За замовчуванням автовакуум починає робити це кожні 200 млн операцій. Запуск ручного вакууму з вакуумом_freeze_min_age встановлений на 0 після об'ємної вставки може допомогти зменшити вплив цього. Більш агресивно ви могли бігати VACUUM FREEZEпо столу після вставки. Це дозволить "скинути годинник", коли відбудеться наступне сканування заморожування.
Якщо ви хочете дізнатися конкретні деталі, перегляньте HEAPTUPLE_LIVEвипадок після дзвінка HeapTupleSatisfiesVacuum()всередину lazy_scan_heap(). Дивіться також HeapTupleSatisfiesVacuum()себе і порівняйте HeapTupleSatisfiesMVCC().
Є ще дві мої презентації, які можуть бути цікавими. Перше відео доступне з http://www.pgcon.org/2015/schedule/events/829.en.html , а друге (що, на мою думку, було трохи краще) на https://www.youtube. com / дивитися? v = L8nErzxPJjQ
EXPLAIN (ANALYZE, BUFFERS) outputs. But, if I understand things correctly, some of the hint bits (at least* ЗВ'ЯЗАНО і*INVALID) може (може) вже встановитиCOMMITабоROLLBACK, правда?