Чи видаляє SELECT мертві рядки, як VACUUM?


9

Я поспіхував VACUUMі помітив деяку несподівану поведінку, коли SELECTінжини рядків із таблиці, здається, зменшують роботу VACUUMпісля цього.

Дані тесту

Примітка: автовакуум вимкнено

CREATE TABLE numbers (num bigint);
ALTER TABLE numbers SET (
  autovacuum_enabled = 'f',
  toast.autovacuum_enabled = 'f'
);

INSERT INTO numbers SELECT generate_series(1, 5000);

Випробування 1

Тепер ми запускаємо оновлення для всіх рядків,

UPDATE numbers SET num = 0;

І коли ми біжимо, VACUUM (VERBOSE) numbers;ми отримуємо,

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 5000 row versions in 23 pages
INFO:  "numbers": found 5000 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6585
There were 0 unused item pointers.

Пробний 2

Тепер ми видаємо ще одну UPDATE, але цього разу додамо SELECTзгодом,

UPDATE numbers SET num = 1;
SELECT * FROM numbers;

І коли ми біжимо, VACUUM (VERBOSE) numbers;ми отримуємо,

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 56 row versions in 22 pages
INFO:  "numbers": found 56 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6586
There were 56 unused item pointers.

Що саме тут відбувається? Чому друга версія, яку я запускаю, після SELECTвилучення мертвих кортежів зі сторінок, які вона відвідує, так само VACUUMвиглядає?

Я запускаю Postgres 11.3 на macOS 10.14.5.


2
Якого клієнта ви використовуєте для запуску своїх команд? Чи ввімкнено функцію автокомісії?
мустаччо

2
Я видаляю питання "Чи VACUUM таблиця в основному просто ВИБІР * З ВІД таблиці під кришкою?" (це не так) Я думаю, що це корисне спостереження, відповідь тут просто в тому, що SELECT може видаляти мертві рядки, і це спільне використання спільного з VACUUM. Наскільки вони відрізняються, буде дуже вичерпна розмова про перекидання XID та ще багато речей. Це питання в основному "Які ще речі робить вакуум, окрім видалення мертвих рядів". (Що було б невиразно)
Еван Керролл

@mustaccio Я робив ці тести за допомогою сценарію Ruby за допомогою ActiveRecord, який використовує дорогоцінний камінь PG під кришкою. Я вважаю, що автокомісія увімкнена за замовчуванням, оскільки вам не потрібно видавати жодних COMMIT, якщо BEGIN не використовується явно.
rafbm

Відповіді:


5

З цього повідомлення на / r / PostgreSQL до відповіді Лауренца Альбе, схоже, що за оновлення може бути відповідальним лише Heap Only Tuples (HOT). З опису гарячих оновлень вsrc/backend/access/heap/README.HOT

Ефективна рекультивація місця відбувається під час пошуку кортежу, коли сторінка майже заповнена (<10% безкоштовно) і може бути заблоковано очищення буфера. Це означає, що UPDATE, DELETEі SELECTможе викликати рекультивацію простору, але часто не під час, INSERT ... VALUESоскільки вона не отримує рядок.

Цитата не в оригінальній відповіді, але решта - цитата,

Щоб підтримати або спростувати цю теорію, запустіть наступний запит:

SELECT n_tup_upd, n_tup_hot_upd
FROM pg_stat_user_tables
WHERE schemaname = 'public' AND relname = 'TABLE_NAME';

Якщо n_tup_hot_updбільший за нуль, ми отримаємо випадок.


Зараз ми говоримо. +1
мустаччо

Гаряче, здається, є хорошим поясненням. Якщо I CREATE INDEX idx_numbers ON numbers USING btree (num), VACUUM вихід буде змінено на INFO: "numbers": removed 5000 row versions in 45 pages. Однак зауважте, що в сценарії без індексу n_tup_hot_updзавжди дорівнює 0, як між ОНОВЛЕННЯМ і ВИБОРОМ, так і між ВИБІР та ВАКУУМ. Я також переконався в тому, щоб переходити SELECT pg_sleep(10)між кожним твердженням, щоб статистика була актуальною (я бачу seq_scan: 2, одна для ОНОВЛЕННЯ та одна для ВИБОРУ).
rafbm

Чи в цьому випадку вибір генерує WAL? У мене було враження, що вибірки взагалі не генерують WAL. Якщо так, це означатиме, що видалення мертвих рядів поширюється на будь-яких рабів. Якщо ні, це означає, що пилосос все ще потрібен на рабі. Це також означало б, що господарі і раби не є ідентичними. Гм, можливо, мені потрібно зробити кілька досліджень і поставити питання та / або відповідь чи два.
Colin 't Hart

1

Так, у спеціальному випадку недекларованої таблиці, SELECT може виконувати ту саму роботу, що і VACUUM (що стосується видалення мертвих рядків).


3
Чи можете ви додати пояснення?
Лоренц Albe
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.