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

select pg_size_pretty (pg_total_relation_size ('test_normal'))

Выход: 6512 МБ

Я использую следующую команду для определения размера секционированной таблицы:

select sum(to_number(pg_size_pretty(pg_total_relation_size(inhrelid::regclass)),'999999999')) from pg_inherits where inhparent = 'test_partition'::regclass

Выход: 6712,1 МБ

Разделенная таблица имеет 1001 раздел. Обе таблицы не имеют индексов или ограничений.

Почему такая большая разница (200 МБ) между двумя таблицами, если размер пустого раздела равен 0 байт?

0
Emissa 4 Фев 2022 в 15:55

2 ответа

Лучший ответ

Основная проблема в том, что вы вызываете to_number(pg_size_pretty(...),'999999999'). pg_size_pretty возвращает такие значения, как 123 MB или 123 GB, оба из которых станут 123, поэтому сумма неверна. И даже если все единицы окажутся одинаковыми, вы все равно получите ошибку округления.

Поэтому вызовите to_number после суммирования размеров.

Конечно, между неразделенной и секционированной таблицами все еще может быть небольшое расхождение.

2
Laurenz Albe 4 Фев 2022 в 16:14

Большое спасибо Лоренц

Я искал другой метод для определения размера секционированной таблицы и нашел этот пост: Получить размер секционированной таблицы (Postgres 10+)

Поэтому я пробую это:

WITH RECURSIVE tables AS (
 SELECT
   c.oid AS parent,
   c.oid AS relid,
   1     AS level
 FROM pg_catalog.pg_class c
 LEFT JOIN pg_catalog.pg_inherits AS i ON c.oid = i.inhrelid
   -- p = partitioned table, r = normal table
 WHERE c.relkind IN ('p')
   -- not having a parent table -> we only get the partition heads
   AND i.inhrelid IS NULL
 UNION ALL
 SELECT
   p.parent         AS parent,
   c.oid            AS relid,
   p.level + 1      AS level
 FROM tables AS p
 LEFT JOIN pg_catalog.pg_inherits AS i ON p.relid = i.inhparent
 LEFT JOIN pg_catalog.pg_class AS c ON c.oid = i.inhrelid AND c.relispartition
 WHERE c.oid IS NOT NULL
)
SELECT
 parent ::REGCLASS                                  AS table_name,
 pg_size_pretty(sum(pg_total_relation_size(relid))) AS pretty_total_size,
 sum(pg_total_relation_size(relid))                 AS total_size
FROM tables
GROUP BY parent
ORDER BY sum(pg_total_relation_size(relid)) DESC

Теперь результат имеет больше смысла!

0
Emissa 4 Фев 2022 в 16:53
Если вы используете Postgres 12 или более позднюю версию, вы можете упростить это до select sum(pg_total_relation_size(relid)) from pg_partition_tree('your_table'::regclass).
 – 
a_horse_with_no_name
4 Фев 2022 в 18:11