Почему postgreSQL ждет, пока выполняется полный вакуумный стол? Данные таблицы 4T - PullRequest
0 голосов
/ 17 марта 2020

У меня раздутая таблица, ее зовут "role_info". Существует около 20 тысяч операций вставки и много операций обновления в день, операций удаления нет. Таблица составляет около 4063 ГБ сейчас. Мы перенесли таблицу в другую базу данных с использованием дампа, и новая таблица занимает около 62 ГБ, поэтому таблица в старой базе данных очень сильно раздута.

PostgreSQL версия: 9.5.4

Схема таблицы ниже:

CREATE TABLE "role_info" (
  "roleId" bigint NOT NULL,
  "playerId" bigint NOT NULL,
  "serverId" int NOT NULL,
  "status" int NOT NULL,
  "baseData" bytea NOT NULL,
  "detailData" bytea NOT NULL,
  PRIMARY KEY ("roleId")
);
CREATE INDEX "idx_role_info_serverId_playerId_roleId" ON "role_info" ("serverId", "playerId", "roleId");

Средний размер поля detailData составляет около 13 КБ в каждой строке.

Есть некоторые SQL результаты выполнения ниже:

1)

SELECT 
    relname AS name,
    pg_stat_get_live_tuples(c.oid) AS lives,
    pg_stat_get_dead_tuples(c.oid) AS deads
FROM pg_class c
ORDER BY deads DESC;

Результат выполнения:

enter image description here

2)

SELECT *, 
       Pg_size_pretty(total_bytes) AS total, 
       Pg_size_pretty(index_bytes) AS INDEX, 
       Pg_size_pretty(toast_bytes) AS toast, 
       Pg_size_pretty(table_bytes) AS TABLE 
FROM   (SELECT *, 
               total_bytes - index_bytes - Coalesce(toast_bytes, 0) AS 
               table_bytes 
        FROM   (SELECT c.oid, 
                       nspname                               AS table_schema, 
                       relname                               AS TABLE_NAME, 
                       c.reltuples                           AS row_estimate, 
                       Pg_total_relation_size(c.oid)         AS total_bytes, 
                       Pg_indexes_size(c.oid)                AS index_bytes, 
                       Pg_total_relation_size(reltoastrelid) AS toast_bytes 
                FROM   pg_class c 
                       LEFT JOIN pg_namespace n 
                              ON n.oid = c.relnamespace 
                WHERE  relkind = 'r') a 
        WHERE  table_schema = 'public' 
        ORDER  BY total_bytes DESC) a; 

Результат выполнения: enter image description here

3)

Я пытался полностью очистить таблицу "role_info", но она была заблокирована каким-то другим процессом и не выполнялся вообще.

select * from pg_stat_activity where query like '%VACUUM%' and query not like '%pg_stat_activity%';

Результат выполнения: enter image description here

select * from pg_locks;

Результат выполнения: enter image description here

Есть параметры вакуума: enter image description here

У меня два вопроса:

  1. Как бороться с вздутием стола? Кажется, что автоочистка не работает.
  2. Почему вакуум заблокирован?

1 Ответ

1 голос
/ 17 марта 2020

С вашими настройками автоочистки он будет спать по 20 мс один раз на каждые 10 страниц (200 cost_limit / 20 cost_dirty). Еще больше, потому что будут также cost_hit и cost_miss. При такой скорости может потребоваться более 12 дней для автоматического вакуумирования таблицы 4063 ГБ, которая в основном нуждается в загрязнении страниц. Это просто время регулирования, не считая фактического рабочего времени или повторного сканирования индексов. Таким образом, фактическое время выполнения может составлять месяцы. Вероятность того, что автовакуум достигнет завершения за один присест, не будучи прерванным чем-либо, может быть довольно низкой. Ваша база данных часто перезагружается? Вы много строите и удаляете индексы для этой таблицы, или добавляете и удаляете разделы, или запускаете ALTER TABLE?

Обратите внимание, что в v12 настройка по умолчанию для autovacuum_vacuum_cost_delay была снижена в 10 раз. только из-за некоторых изменений в коде в v12, это потому, что мы поняли, что настройка по умолчанию просто не имеет смысла на современном оборудовании. Так что, вероятно, имеет смысл сделать бэкпорт для этого изменения существующей базы данных, если не дальше go. До 12 вы не можете опускаться до менее 1 мс, но вы можете уменьшить его до 1 мс, а также либо увеличить параметр autovacuum_vacuum_cost_delay, либо понизить значениеuum_cost_page_ *.

Теперь этот анализ основан на том, что таблица уже чрезвычайно раздутой. Почему автоочистка не помешала этому раздуваться в первую очередь, когда стол был достаточно маленьким, чтобы его можно было за разумное время? Сложно сказать. У нас действительно нет никаких доказательств того, что произошло тогда. Возможно, ваши настройки были еще более ограничены, чем сейчас (хотя маловероятно, что, похоже, вы только что приняли значения по умолчанию), возможно, что-то постоянно прерывалось. Что такое «autovacuum_count» из pg_stat_all_tables для таблицы и таблицы тостов?

Почему вакуум полностью заблокирован?

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

Вам нужно окно обслуживания, где никто больше не использует таблицу. Если вы думаете, что уже находитесь в таком окне, вам следует посмотреть текст запроса для процесса, выполняющего блокировку. Поскольку блокировка уже удерживается ShareUpdateExclusive , ее удерживает не обычный запрос / DML, а какой-то DDL или операция обслуживания.

Если вы не можете открыть окно обслуживания теперь, тогда вы можете по крайней мере сделать ручной ВАКУУМ без ПОЛНОГО. Это занимает гораздо более слабую блокировку. Это, вероятно, не приведет к значительному сокращению таблицы, но, по крайней мере, должно освободить место для внутреннего повторного использования, поэтому оно перестанет становиться еще больше, пока вы не поймете, когда можете запланировать интервал обслуживания или каковы ваши дальнейшие шаги.

...