Как проверить, работает ли TOAST на определенной таблице в postgres

У меня есть таблица, которая содержит два текстовых поля, которые содержать много текста. Почему-то наша таблица начала расти в геометрической прогрессии. Я подозреваю, что тост (сжатие для текстовых полей в postgres) не работает автоматически. В нашем определении таблицы мы не определили предложение для принудительного сжатия этих полей. Есть ли способ проверить, работает ли сжатие на этой таблице или нет?

4 ответов


документы . . .

если какой-либо из столбцов таблицы тост, то таблица будет иметь связанная таблица тостов, OID которой хранится в таблице pg_class.вход релтоастрелида. Out-of-line TOASTed значения хранятся в таблица тостов, как описано более подробно ниже.

таким образом, вы можете определить, существует ли таблица тостов, запросив системный каталог pg_class. Это должно приблизить тебя к ... то, что ты ищешь.

select t1.oid, t1.relname, t1.relkind, t2.relkind, t2.relpages, t2.reltuples
from pg_class t1
inner join pg_class t2
on t1.reltoastrelid = t2.oid
where t1.relkind = 'r'
  and t2.relkind = 't';

в psql, вы можете использовать \d+. Я буду использовать системный каталог pg_class в качестве примера; вы будете использовать свое собственное имя таблицы.

sandbox=# \d+ pg_class
     Column     |   Type    | Modifiers | Storage  | Stats target | Description 
----------------+-----------+-----------+----------+--------------+-------------
 relname        | name      | not null  | plain    |              | 
 relnamespace   | oid       | not null  | plain    |              | 
 [snip]
 relacl         | aclitem[] |           | extended |              | 
 reloptions     | text[]    |           | extended |              | 

где хранилище "расширено", PostgreSQL попытается уменьшить размер строки, сначала сжимая, а затем сохраняя данные вне строки. Где хранилище "основное" (не показано), PostgreSQL попытается сжать.

в вашем конкретном случае вам может быть полезно отслеживать изменения размера с течением времени. Вы можете использовать этот запрос и сохранить результаты для последующего анализа.

select table_catalog, table_schema, table_name, 
       pg_total_relation_size(table_catalog || '.' || table_schema|| '.' || table_name) as pg_total_relation_size,
       pg_relation_size(table_catalog || '.' || table_schema|| '.' || table_name) as pg_relation_size,
       pg_table_size(table_catalog || '.' || table_schema|| '.' || table_name) as pg_table_size
from information_schema.tables

функции администратора PostgreSQL содержит информацию о том, что каждая функция включает в свои расчеты.


Это старый, но у меня недавно был некоторый успех с аналогичной проблемой. Анализ VERBOSE показал, что пара наших таблиц выросла до > 1 страницы диска на кортеж, и объяснить анализ показал, что последовательное сканирование занимает до 30 секунд на таблице из 27K строк. Оценки количества активных рядов становились все более и более отдаленными.

после долгих поисков я узнал, что строки можно пылесосить, только если нет транзакции, которая была открыта с тех пор, как они были усовершенствованный. Эта таблица переписывалась каждые 3 минуты, и было соединение, которое "простаивало в транзакции", которому было 3 дня. Ты можешь посчитать.

в этом случае, нам пришлось

  1. убить соединение с открытой транзакцией
  2. переподключение в базу данных. К сожалению, максимальный идентификатор транзакции для строк, которые можно пропылесосить, в настоящее время (по состоянию на 9.3) хранится в соединении, поэтому вакуум полный не будет работа.
  3. VACUUUM полный ваш стол (это выведет эксклюзивный замок доступа,который заблокирует все, включая чтение. Вы можете сначала запустить вакуум (неблокирующий), чтобы ускорить время полного вакуума).

возможно, это не ваша проблема, но если вы хотите увидеть, затронуты ли таблицы в вашей собственной базе данных, я написал запрос на порядок таблиц по среднему количеству кортежей, хранящихся на странице диска. Таблицы с большими строками должны быть на top-ANALYZE VERBOSE должен дать вам представление о соотношении мертвых и живых кортежей в этих таблицах. действующий на 9,3 - это, вероятно, потребует некоторых незначительных настроек для других версий:

SELECT rolname AS owner,
       nspname AS schemaname
     , relname AS tablename
     , relpages, reltuples, (reltuples::FLOAT / relpages::FLOAT) AS tuples_per_page
FROM pg_class
JOIN pg_namespace ON relnamespace = pg_namespace.oid
JOIN pg_roles     ON relowner     = pg_roles.oid
WHERE relkind = 'r' AND relpages > 20 AND reltuples > 1000
  AND nspname != 'pg_catalog'
ORDER BY tuples_per_page;

вы можете увидеть, какие запросы psql запускает, запустив его с помощью -E параметр, затем запуск обычных команд:

в этом случае тот, который спустился, был первым поиском oid вашей таблицы:

SELECT c.oid,
  n.nspname,
  c.relname
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname ~ '^(YOUR_TABLE_NAME_HERE)$'
  AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 2, 3;

затем он выполняет это, чтобы найти больше статистики об этом:

SELECT a.attname,                                                                                                                                          pg_catalog.format_type(a.atttypid, a.atttypmod),
  (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
   FROM pg_catalog.pg_attrdef d
   WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef),
  a.attnotnull, a.attnum,
  (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t
   WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation,
  NULL AS indexdef,
  NULL AS attfdwoptions,
  a.attstorage,
  CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget, pg_catalog.col_description(a.attrelid, a.attnum)
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = '57692' AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum;

x.attrstorage-это то, о чем вы заботитесь p - это равнина, x продлен я ставлю.


Если пылесосить таблицу rhe обнажает ее до 19GB от 80GB, то, что вы, вероятно, видите, это MVCC на работе: мертвые строки занимают место до вакуумирования или повторного использования.

http://wiki.postgresql.org/wiki/MVCC