F.40. pg_csm — оценка сжимаемости таблиц и индексов с помощью CSM#

F.40. pg_csm — оценка сжимаемости таблиц и индексов с помощью CSM

F.40. pg_csm — оценка сжимаемости таблиц и индексов с помощью CSM #

F.40.1. Обзор #

pg_csm — расширение PostgreSQL для диагностики Compression Storage Manager (CSM).

Расширение предоставляет SQL-интерфейс к четырём направлениям диагностики CSM:

  • Информация о storage manager. Функция smgr_info показывает, какой storage manager используется для конкретной relation, и возвращает его параметры — алгоритм сжатия и размер страницы.

  • Анализ сжатия. Функция csm_compress_analysis читает страницы relation, сжимает их во временном буфере и возвращает статистику по каждому алгоритму. Это позволяет подобрать алгоритм и размер страницы до того, как данные будут физически перезаписаны.

  • Статистика overflow fork. Функция csm_overflow_fork_stat показывает, как заполнен overflow fork CSM-relation: ёмкость, использованные и свободные блоки, распределение batch по размеру. Это основной инструмент для оценки фрагментации overflow-пространства.

  • Статистика кешей CSM. Функция csm_cache_stat возвращает накопленные счётчики операций и промахов для внутренних кешей CSM в shared memory.

pg_csm входит в состав поставки СУБД. Compression Storage Manager реализован на уровне ядра СУБД и доступен всегда, поэтому расширение не требует отдельной сборки внешнего storage manager.

F.40.2. Подключение расширения #

Расширение подключается в нужной базе данных стандартной командой PostgreSQL:

CREATE EXTENSION pg_csm;

После подключения становятся доступны функции smgr_info, csm_compress_analysis, csm_overflow_fork_stat и csm_cache_stat.

F.40.3. Быстрый старт #

Узнать, какой storage manager используется для таблицы:

SELECT smgr_info('public.orders'::regclass);

Оценить сжимаемость таблицы всеми алгоритмами:

SELECT *
FROM csm_compress_analysis('public.orders');

Посмотреть статистику overflow fork CSM-таблицы:

CHECKPOINT;
SELECT *
FROM csm_overflow_fork_stat('public.orders'::regclass);

Посмотреть статистику внутреннего кэша CSM:

SELECT * FROM csm_cache_stat('ctl');

F.40.4. Настройка сжатого хранения #

Параметры CSM задаются через storage options relation.

Пример создания таблицы со сжатием:

CREATE TABLE orders (
    id bigint,
    customer_id bigint,
    payload jsonb
) WITH (
    compression = zstd,
    compression_page = 1024
);

Пример создания индекса со сжатием:

CREATE INDEX orders_customer_id_idx
ON orders (customer_id)
WITH (
    compression = zstd,
    compression_page = 4096
);

Изменить параметры хранения можно с помощью ALTER TABLE или ALTER INDEX:

ALTER TABLE orders
SET (
    compression = pglz,
    compression_page = 2048
);
ALTER INDEX orders_customer_id_idx
SET (
    compression_page = 1024
);

Отключить сжатие для relation можно с помощью compression = off:

CREATE TABLE orders_plain (
    id bigint,
    payload text
) WITH (
    compression = off
);

В тестах расширения используются значения compression_page: 1024, 2048 и 4096.

F.40.5. smgr_info #

smgr_info(
    rel regclass,
    do_switch bool DEFAULT false
)
RETURNS cstring

Возвращает строку с описанием storage manager, используемого для таблицы или индекса. При do_switch = true перед выводом принудительно завершает выбор storage manager для relation, не изменяя пользовательские данные.

F.40.5.1. Аргументы #

АргументТипПо умолчаниюОписание
relregclassТаблица или индекс.
do_switchboolfalseЕсли true, перед выводом выполняется выбор конкретного storage manager. Полезно, когда relation ещё находится в состоянии выбора (Switcher).

F.40.5.2. Возвращаемое значение #

Возможные значения возвращаемой строки:

ЗначениеОписание
SwitcherКонкретный storage manager ещё не выбран.
Storage Manager with compression (algorithm: ..., page size: ...)Relation использует Compression Storage Manager.
Magnatic diskRelation использует обычный дисковый storage manager PostgreSQL.
The storage manager defined by the extensionИспользуется внешний storage manager, определённый расширением.

F.40.5.3. Примеры #

Проверить storage manager таблицы:

SELECT smgr_info('public.orders'::regclass);
                             smgr_info
----------------------------------------------------------------------
 Storage Manager with compression (algorithm: zstd, page size: 1024)
(1 row)

Завершить выбор storage manager и сразу получить результат:

SELECT smgr_info('public.orders'::regclass, true);
                             smgr_info
----------------------------------------------------------------------
 Storage Manager with compression (algorithm: zstd, page size: 1024)
(1 row)

F.40.5.4. Как интерпретировать результат #

Если функция возвращает Switcher, storage manager для relation ещё не определён. Повторный вызов с do_switch = true завершит выбор и вернёт итоговое значение.

Для CSM-relation в строке отображаются алгоритм и размер страницы, заданные через compression и compression_page.

F.40.6. csm_compress_analysis #

csm_compress_analysis(
    rel regclass,
    compress_alg text DEFAULT 'all',
    sample_rate float8 DEFAULT 1.0
)
RETURNS TABLE (
    reloid oid,
    page_cnt int4,
    alg_name text,
    avg_compress float4,
    avg_page_sz int8,
    pages_over_1k int4,
    pages_over_2k int4,
    pages_over_4k int4
)

Читает страницы relation, сжимает их во временном буфере и возвращает агрегированную статистику по каждому алгоритму. Данные relation при этом не изменяются.

F.40.6.1. Аргументы #

АргументТипПо умолчаниюОписание
relregclassИмя или OID таблицы/индекса. Рекомендуется указывать имя со схемой, например 'public.orders'.
compress_algtext'all'Алгоритм сжатия. Допустимые значения: all, zstd, pglz, lz4, cpy. Значение all запускает анализ для всех доступных алгоритмов.
sample_ratefloat81.0Доля страниц для анализа. Значение должно быть больше 0.0 и меньше или равно 1.0.

F.40.6.2. Возвращаемые колонки #

КолонкаТипОписание
reloidoidOID проанализированной relation.
page_cntint4Количество страниц, использованных при анализе.
alg_nametextАлгоритм сжатия.
avg_compressfloat4Средний коэффициент сжатия: отношение среднего размера сжатой страницы к исходному. Чем меньше, тем сильнее сжатие.
avg_page_szint8Средний размер страницы после сжатия, в байтах.
pages_over_1kint4Количество страниц, размер которых после сжатия превысил 1 KB.
pages_over_2kint4Количество страниц, размер которых после сжатия превысил 2 KB.
pages_over_4kint4Количество страниц, размер которых после сжатия превысил 4 KB.

Если relation не содержит страниц, page_cnt равен 0, то статистические колонки возвращаются как NULL.

F.40.6.3. Примеры #

Сравнить все алгоритмы и отсортировать результат по среднему размеру страницы:

SELECT *
FROM csm_compress_analysis('public.orders', 'all', 1.0)
ORDER BY avg_page_sz;
 reloid | page_cnt | alg_name | avg_compress | avg_page_sz | pages_over_1k | pages_over_2k | pages_over_4k
--------+----------+----------+--------------+-------------+---------------+---------------+---------------
  16384 |     1250 | zstd     |         0.38 |        3113 |          1180 |           948 |           118
  16384 |     1250 | lz4      |         0.44 |        3604 |          1212 |          1047 |           309
  16384 |     1250 | pglz     |         0.47 |        3850 |          1224 |          1103 |           421
  16384 |     1250 | cpy      |         0.53 |        4341 |          1238 |          1186 |           702
(4 rows)

Быстро оценить большую таблицу по 5% страниц:

SELECT *
FROM csm_compress_analysis('public.orders', 'all', 0.05)
ORDER BY avg_compress;
 reloid | page_cnt | alg_name | avg_compress | avg_page_sz | pages_over_1k | pages_over_2k | pages_over_4k
--------+----------+----------+--------------+-------------+---------------+---------------+---------------
  16384 |       63 | zstd     |         0.37 |        3031 |            58 |            46 |             6
  16384 |       63 | lz4      |         0.43 |        3522 |            60 |            51 |            15
  16384 |       63 | pglz     |         0.46 |        3768 |            61 |            54 |            20
  16384 |       63 | cpy      |         0.52 |        4260 |            62 |            58 |            34
(4 rows)

Проверить только zstd:

SELECT *
FROM csm_compress_analysis('public.orders', 'zstd');
 reloid | page_cnt | alg_name | avg_compress | avg_page_sz | pages_over_1k | pages_over_2k | pages_over_4k
--------+----------+----------+--------------+-------------+---------------+---------------+---------------
  16384 |     1250 | zstd     |         0.38 |        3113 |          1180 |           948 |           118
(1 row)

Проанализировать индекс:

SELECT *
FROM csm_compress_analysis('public.orders_customer_id_idx', 'all');
 reloid | page_cnt | alg_name | avg_compress | avg_page_sz | pages_over_1k | pages_over_2k | pages_over_4k
--------+----------+----------+--------------+-------------+---------------+---------------+---------------
  16402 |      275 | zstd     |         0.21 |        1720 |           201 |            48 |             0
  16402 |      275 | lz4      |         0.26 |        2130 |           231 |            89 |             0
  16402 |      275 | pglz     |         0.29 |        2376 |           249 |           121 |             2
  16402 |      275 | cpy      |         0.33 |        2703 |           261 |           158 |             8
(4 rows)

F.40.6.4. Как интерпретировать результат #

Главные поля — avg_compress, avg_page_sz и пороговые счётчики pages_over_1k, pages_over_2k, pages_over_4k.

avg_compress = 0.45 означает, что средняя сжатая страница занимает около 45% от исходного размера.

Если avg_page_sz значительно меньше выбранного compression_page, заданный размер страницы достаточен для большинства данных.

Если многие страницы попадают в pages_over_4k, возможно, нужен больший compression_page или другой алгоритм.

Если zstd даёт лучшее сжатие, но нагрузка чувствительна к CPU, следует дополнительно оценить стоимость сжатия/распаковки на реальной рабочей нагрузке.

F.40.6.5. Ограничения #

  • Поддерживаются только обычные таблицы и индексы. Представления, sequences и другие типы relation вернут ошибку.

  • Полный анализ большой relation может занять заметное время: страницы читаются и сжимаются в backend-процессе.

  • При sample_rate < 1.0 результат является приблизительным.

  • avg_compress и avg_page_sz описывают ожидаемую сжимаемость страниц, но не заменяют проверку производительности на реальной нагрузке.

F.40.7. csm_overflow_fork_stat #

csm_overflow_fork_stat(
    rel regclass,
    OUT relname text,
    OUT is_csm boolean,
    OUT compression_alg text,
    OUT compression_page_size int4,
    OUT overflow_physical_blocks int8,
    OUT overflow_extent_count int8,
    OUT overflow_data_capacity_blocks int8,
    OUT used_blocks int8,
    OUT free_blocks int8,
    OUT overflow_batches int8,
    OUT overflow_blocks_in_batches int8,
    OUT avg_batch_len float8,
    OUT batch_count_by_len int8[],
    OUT block_count_by_batch_len int8[]
)

Возвращает статистику overflow fork для указанной relation. Overflow fork хранит сжатые страницы CSM, которые не помещаются в стандартный блок PostgreSQL. Relation открывается с блокировкой AccessShareLock; для non-CSM relation все поля кроме relname и is_csm возвращаются как NULL.

Для актуальной статистики рекомендуется выполнить CHECKPOINT перед вызовом — иначе несброшенные грязные буферы не попадут в результат.

F.40.7.1. Аргументы #

АргументТипПо умолчаниюОписание
relregclassТаблица или индекс. Relation должна иметь физическое хранилище.

F.40.7.2. Возвращаемые колонки #

КолонкаТипОписание
relnametextИмя relation со схемой.
is_csmbooleantrue, если relation использует CSM.
compression_algtextАлгоритм сжатия (zstd, pglz, lz4, cpy) или off. NULL для non-CSM.
compression_page_sizeint4Настроенный размер сжатой страницы в KB. NULL для non-CSM.
overflow_physical_blocksint8Количество физических блоков в overflow fork, включая заголовки extents.
overflow_extent_countint8Количество overflow extents.
overflow_data_capacity_blocksint8Количество блоков данных: overflow_physical_blocks − overflow_extent_count.
used_blocksint8Количество блоков данных, помеченных как используемые в bitmap extent.
free_blocksint8Количество блоков данных, помеченных как свободные в bitmap extent.
overflow_batchesint8Количество найденных overflow batch.
overflow_blocks_in_batchesint8Суммарное количество блоков во всех найденных batch.
avg_batch_lenfloat8Средняя длина batch в блоках, округлена до двух знаков.
batch_count_by_lenint8[]Гистограмма: элемент [N] — количество batch длиной N блоков (1–8).
block_count_by_batch_lenint8[]Гистограмма: элемент [N] — количество блоков в batch длиной N (1–8).

F.40.7.3. Примеры #

Статистика для non-CSM таблицы:

SELECT relname, is_csm
FROM csm_overflow_fork_stat('public.orders_plain'::regclass);
      relname        | is_csm
---------------------+--------
 public.orders_plain | f
(1 row)

Статистика для CSM-таблицы после вставки данных:

CHECKPOINT;
SELECT *
FROM csm_overflow_fork_stat('public.orders'::regclass);
    relname    | is_csm | compression_alg | compression_page_size | overflow_physical_blocks | overflow_extent_count | overflow_data_capacity_blocks | used_blocks | free_blocks | overflow_batches | overflow_blocks_in_batches | avg_batch_len |   batch_count_by_len   | block_count_by_batch_len
---------------+--------+-----------------+-----------------------+--------------------------+-----------------------+-------------------------------+-------------+-------------+------------------+----------------------------+---------------+------------------------+--------------------------
 public.orders | t      | zstd            |                     1 |                      512 |                     1 |                           511 |         304 |         207 |               38 |                        304 |             8 | {0,0,0,0,0,0,0,38}     | {0,0,0,0,0,0,0,304}
(1 row)

F.40.7.4. Как интерпретировать результат #

used_blocks + free_blocks должно совпадать с overflow_data_capacity_blocks.

avg_batch_len близкая к 8 говорит о том, что большинство данных упаковано в максимальные batch — overflow fork используется эффективно.

Высокое значение free_blocks относительно overflow_data_capacity_blocks указывает на фрагментацию overflow-пространства.

F.40.7.5. Ограничения #

  • Функция отражает состояние overflow fork на момент последнего CHECKPOINT. Несброшенные грязные буферы в результат не попадают.

  • Relation без физического хранилища (представления и т.п.) вернут ошибку.

F.40.8. csm_cache_stat #

csm_cache_stat(
    cache_name text
)
RETURNS TABLE (
    get_total bigint,
    get_miss bigint,
    put_total bigint,
    put_evict bigint,
    blocks_used bigint
)

Возвращает накопленные счётчики операций для внутреннего кеша CSM в shared memory. Предназначена для диагностики эффективности кеширования. Статистика накапливается с момента запуска кластера и не сбрасывается.

F.40.8.1. Аргументы #

АргументТипПо умолчаниюОписание
cache_nametextИмя кэша. Допустимые значения: ctl (кэш управляющих структур CSM), ovr (кэш размеров overflow страниц), extent (кэш overflow extents).

F.40.8.2. Возвращаемые колонки #

КолонкаТипОписание
get_totalbigintСуммарное количество операций чтения из кэша.
get_missbigintКоличество промахов: данные не найдены в кэше.
put_totalbigintСуммарное количество операций записи в кэш.
put_evictbigintКоличество вытеснений из кэша.
blocks_usedbigintТекущее количество занятых (pinned) записей в кэше.

F.40.8.3. Примеры #

Получить статистику кэша управляющих структур:

SELECT * FROM csm_cache_stat('ctl');
 get_total | get_miss | put_total | put_evict | blocks_used
-----------+----------+-----------+-----------+-------------
      1024 |       12 |       512 |         0 |           8
(1 row)

Обращение к несуществующему кешу вернёт ошибку:

SELECT * FROM csm_cache_stat('unknown');
-- ERROR:  storage manager cache 'unknown' not exist

F.40.8.4. Как интерпретировать результат #

Доля промахов (get_miss / get_total) — основной показатель эффективности кеша. Высокое значение может указывать на недостаточный размер shared memory для CSM.

Рост put_evict означает, что кеш переполняется и вынужден вытеснять записи; при частых вытеснениях стоит рассмотреть увеличение параметров памяти CSM.

F.40.8.5. Ограничения #

  • Статистика накапливается с момента запуска кластера и не сбрасывается.

  • Допустимые значения cache_name: только ctl, ovr, extent. Любое другое значение вернёт ошибку.

F.40.9. Примечания и ограничения #

  • Все функции работают в режиме read-only: данные relation не изменяются, блокировка AccessShareLock.

  • Compression Storage Manager реализован на уровне ядра СУБД; pg_csm предоставляет SQL-интерфейс для диагностики и не требует отдельной сборки внешнего storage manager.