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
, правда?