Почему VACUUM ANALYZE не удаляет все мертвые кортежи?


8

Мы запускаем «руководство» VACUUM ANALYZE VERBOSEдля некоторых из наших больших таблиц после того, как вносим DELETE/INSERTв них серьезные изменения. Кажется, что это работает без проблем, хотя иногда работа таблицы VACUUMбудет выполняться часами (см. Этот пост для похожих проблем и рассуждений).

Проведя дополнительные исследования, я обнаружил, что у нас есть большие таблицы с большим количеством мертвых кортежей даже после запуска VACUUM. Например, вот некоторые статистические данные, полученные из запроса в этом ответе .

-[ RECORD 50 ]--+---------------------------
relname         | example_a
last_vacuum     | 2014-09-23 01:43
last_autovacuum | 2014-08-01 01:19
n_tup           |    199,169,568
dead_tup        |    111,048,906
av_threshold    |     39,833,964
expect_av       | *
-[ RECORD 51 ]--+---------------------------
relname         | example_b
last_vacuum     | 2014-09-23 01:48
last_autovacuum | 2014-08-30 12:40
n_tup           |    216,596,624
dead_tup        |    117,224,220
av_threshold    |     43,319,375
expect_av       | *
-[ RECORD 52 ]--+---------------------------
relname         | example_c
last_vacuum     | 2014-09-23 01:55
last_autovacuum | 2014-09-23 18:25
n_tup           |    309,831,136
dead_tup        |    125,047,233
av_threshold    |     61,966,277
expect_av       | *

Последнее поле утверждает, что эти (и большинство таблиц) будут соответствовать порогу для автовакуума. Однако, просто запустив VACUUM ANALYZE VEBOSEкаждую из этих таблиц, не должно ли число мертвых кортежей быть 0 (или близко к 0, а не 125M из 300M)?

В документации говорится:

VACUUM восстанавливает память, занятую мертвыми кортежами.

Значит ли это, что наша VACUUMне работает?


ОБНОВИТЬ

По запросу в repsonse вот несколько журналов с VERBOSEзаданий:

INFO:  vacuuming "public.example_1"
INFO:  scanned index "idx_example_1_on_gp_id_and_dd_id" to remove 378386 row versions
DETAIL:  CPU 1.83s/3.42u sec elapsed 23.01 sec.
INFO:  scanned index "index_example_1_on_q_id" to remove 378386 row versions
DETAIL:  CPU 2.10s/3.91u sec elapsed 18.92 sec.
INFO:  "example_1": removed 378386 row versions in 7085 pages
DETAIL:  CPU 0.09s/0.05u sec elapsed 0.19 sec.
INFO:  index "idx_example_1_on_gp_id_and_dd_id" now contains 30347438 row versions in 291065 pages
DETAIL:  378386 index row versions were removed.
165587 index pages have been deleted, 164287 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  index "index_example_1_on_q_id" now contains 30347438 row versions in 333287 pages
DETAIL:  378386 index row versions were removed.
152773 index pages have been deleted, 152757 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "example_1": found 1773 removable, 401984 nonremovable row versions in 14438 out of 1493006 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 10567 unused item pointers.
0 pages are entirely empty.
CPU 4.26s/7.51u sec elapsed 46.10 sec.
INFO:  vacuuming "pg_toast.pg_toast_17917"
INFO:  index "pg_toast_17917_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_17917": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_1"
INFO:  "example_1": scanned 30000 of 1493006 pages, containing 611502 live rows and 0 dead rows; 30000 rows in sample, 40563141 estimated total rows

Эта таблица теперь показывает 0 мертвых кортежей в статистике. VACUUMСегодня утром на большинстве столов намного меньше мертвых кортежей, поэтому работает либо наш, либо автовакуум.

У нас есть несколько таблиц, которые ничего не выводят и все же показывают мертвые кортежи:

-[ RECORD 49 ]--+---------------------------
relname         | example_2
last_vacuum     | 2014-09-23 02:23
last_autovacuum | 2014-09-02 14:30
n_tup           |    117,914,944
dead_tup        |     34,507,388
av_threshold    |     23,583,039
expect_av       | *

Пару раз я видел в журналах, где индексы будут проверяться снова и снова. Кажется, это соответствует долгосрочным VACUUMработам. Есть идеи почему? Это просто работает вокруг блокировки записи (я не думаю, что какие-либо записи происходили во время выполнения этих заданий.)

INFO:  vacuuming "public.example_2"
...
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2795959 row versions
DETAIL:  CPU 3.88s/16.54u sec elapsed 23.09 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2795959 row versions
DETAIL:  CPU 6.74s/21.13u sec elapsed 84.64 sec.
INFO:  "example_2": removed 2795959 row versions in 48214 pages
DETAIL:  CPU 0.71s/0.32u sec elapsed 33.65 sec.
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2591011 row versions
DETAIL:  CPU 2.84s/16.11u sec elapsed 19.28 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2591011 row versions
DETAIL:  CPU 5.46s/22.70u sec elapsed 130.57 sec.
INFO:  "example_2": removed 2591011 row versions in 45539 pages
DETAIL:  CPU 0.67s/0.38u sec elapsed 15.16 sec.
INFO:  index "index_example_2_on_gsg_id_and_dd_id" now contains 123807784 row versions in 1560915 pages
DETAIL:  108836958 index row versions were removed.
1100790 index pages have been deleted, 718471 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.25 sec.
INFO:  index "index_example_2_on_q_id" now contains 123807784 row versions in 1886087 pages
DETAIL:  110336259 index row versions were removed.
1058063 index pages have been deleted, 266983 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.07 sec.
INFO:  "example_2": found 124808 removable, 1355901 nonremovable row versions in 2086343 out of 6966379 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 7858495 unused item pointers.
0 pages are entirely empty.
CPU 595.49s/2130.13u sec elapsed 5656.34 sec.
INFO:  vacuuming "pg_toast.pg_toast_18079"
INFO:  index "pg_toast_18079_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_18079": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_2"
INFO:  "example_2": scanned 30000 of 6966379 pages, containing 528443 live rows and 522 dead rows; 30000 rows in sample, 152953760 estimated total rows

0 dead row versions cannot be removed yet.показывает вам не придется долго выполняющихся транзакций , которые блокируют удаление омертвевших кортежей.
Эрвин Брандштеттер,

Ответы:


10

VACUUM может удалять только мертвые кортежи, которые давно мертвы, то есть мертвы для всех возможных применений. Если у вас есть долгоживущие транзакции, они могут помешать удалению недавно мертвых кортежей.

Это пример ситуации, когда долгоживущая транзакция препятствовала удалению:

INFO:  "pgbench_accounts": found 0 removable, 2999042 nonremovable row versions in 49181 out of 163935 pages
DETAIL:  2999000 dead row versions cannot be removed yet.

Это не действительно долгоживущие транзакции, а долгоживущие снимки. Конечно, длительный оператор выбора или вставки сделает это. Для уровней изоляции выше, чем для фиксации чтения, вся транзакция будет сохранять снимок до тех пор, пока он не будет отключен, поэтому, если кто-то откроет повторяющуюся транзакцию чтения, а затем уйдет в отпуск, не фиксируя ее, это будет проблемой. Готовые транзакции тоже будут зависать (если вы не знаете, что такое подготовленная транзакция, вы, вероятно, не используете их).

Приведенные вами примеры не указывают на проблему, но вы также говорите, что проблема была решена к тому времени. Если это повторяющаяся проблема, вам, вероятно, следует начать регистрировать выходные данные операторов VACUUM VERBOSE, чтобы можно было найти информацию, охватывающую период, в течение которого существует проблема.

Многократные проходы по индексу происходят из-за ваших настроек maintenance_work_mem. Он может удалять только один кортеж на каждые 6 байтов памяти на каждом проходе по индексу, и ему нужно сделать несколько проходов, если вам нужно удалить больше этого. Таким образом, увеличение maintenance_work_mem поможет.


Можете ли вы привести пример того, какими могут быть «долгоживущие транзакции»? Вы имеете в виду длительный запрос к базе данных или INSERT/ IMPORT? Или вы имеете в виду что-то более длинное, чем открытое / закрытое соединение?
jwadsack

4

Размер физической таблицы обычно (за исключением произвольной обрезки съемных страниц с конца таблицы) не уменьшается при запуске VACUUM(или VACUUM ANALYZE). Вам нужно бежать, VACUUM FULLчтобы фактически сжать стол.

Это цитата из соответствующего ответа, который имеет более подробную информацию:

В соответствии с документацией (всего несколько строк ниже вашей цитаты):

Обычный VACUUM(без FULL) просто восстанавливает пространство и делает его доступным для повторного использования. Эта форма команды может работать параллельно с обычным чтением и записью таблицы, поскольку исключительная блокировка не получается. Однако дополнительное пространство не возвращается операционной системе (в большинстве случаев);

Больше здесь:

Вас заинтересует pg_repack , который может делать то же самое, что и VACUUM FULLбез эксклюзивных блокировок.


1
Извините, если мой вопрос не был ясен, но я спрашивал об оставшихся мертвых кортежах. Я знаю, что VACUUMбез FULLне уменьшит размер на диске, и я в порядке с этим. Я упомянул большую таблицу из-за поста, который я связал с первым заявлением о том, что настроенная агрессивная вакуумная стратегия будет «победой ... если есть большие таблицы, строки которых никогда не удаляются и не обновляются». Наши большие столы меняются ежедневно.
jwadsack
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.