64.3. Compression Storage Manager#

64.3. Compression Storage Manager

64.3. Compression Storage Manager #

Compression Storage Manager (CSM) — это механизм физического хранения, который позволяет размещать страницы поддерживаемых таблиц, материализованных представлений и индексов на диске в сжатом виде. Для пользователя и приложения такие объекты остаются обычными объектами PostgreSQL: с ними работают теми же SQL-командами, а сжатие и распаковка выполняются прозрачно на уровне менеджера хранения.

CSM помогает уменьшить размер данных на диске и сократить объем операций ввода-вывода для объектов, которые хорошо поддаются сжатию. При записи страницы сжимаются выбранным алгоритмом, а при чтении восстанавливаются в обычный формат страниц PostgreSQL. Управление CSM выполняется через параметры хранения самого объекта, поэтому сжатие можно включать и настраивать отдельно для конкретных таблиц, материализованных представлений и индексов.

64.3.1. Обзор #

CSM работает на уровне менеджера хранения. Это означает, что механизм применяется к физическим страницам отношения (relation), а не к отдельным строкам или значениям столбцов. В памяти PostgreSQL продолжает использовать обычные страницы, а на диске CSM может хранить их более компактно.

Сжатие включается через параметры хранения:

compression = pglz | lz4 | zstd
compression_page = 1024 | 2048 | 4096

Если указано compression = off, CSM для отношения не используется.

На практике CSM полезен для больших таблиц и индексов, когда экономия места на диске и уменьшение объема ввода-вывода могут быть важнее дополнительных затрат CPU на сжатие и распаковку.

64.3.2. Сравнение с другими механизмами сжатия #

CSM не заменяет TOAST и сжатие на уровне столбцов. Эти механизмы решают разные задачи и работают на разных уровнях.

МеханизмУровень работыОсновная задача
TOASTБольшие значения отдельных varlena-атрибутовХранение значений, которые не помещаются в строку
Сжатие на уровне столбцовОтдельные значения столбцовСжатие значений перед размещением в кортеже
CSMФизические страницы relationСжатие физического хранения таблиц, материализованных представлений и индексов

TOAST применяется к крупным значениям, например большим text, bytea или jsonb. Сжатие на уровне столбцов управляет сжатием отдельных значений столбцов. CSM работает ниже: он получает уже сформированные страницы relation и сжимает их физическое представление.

Благодаря этому CSM может применяться не только к heap-таблицам, но и к поддерживаемым индексам. Это важное отличие от механизмов, ориентированных только на данные таблиц.

64.3.3. Поддерживаемые объекты #

64.3.3.1. Таблицы #

CSM поддерживается для обычных таблиц, использующих метод доступа heap.

CREATE TABLE events (
    id bigint,
    created_at timestamptz,
    payload jsonb
) WITH (
    compression = zstd,
    compression_page = 2048
);

64.3.3.2. Индексы #

CSM поддерживается для индексов с методами доступа btree и hash.

CREATE INDEX events_created_at_idx
ON events USING btree (created_at)
WITH (
    compression = lz4,
    compression_page = 2048
);

Индексы с другими методами доступа не следует считать поддерживаемыми CSM, если это явно не указано в документации конкретной версии продукта.

64.3.3.3. Материализованные представления #

Материализованные представления, использующие heap-хранение, могут использовать CSM так же, как обычные heap-таблицы.

CREATE MATERIALIZED VIEW recent_events
WITH (
    compression = zstd,
    compression_page = 2048
) AS
SELECT *
FROM events
WHERE created_at >= now() - interval '30 days';

64.3.3.4. Сводная таблица поддержки #

Объект или метод доступаПоддержка CSM
Обычная таблица с методом доступа heapДа
Материализованное представление с heap-хранениемДа
Индекс с методом доступа btreeДа
Индекс с методом доступа hashДа
Таблица с методом доступа tde_heapНет
Таблица с методом доступа, отличным от heapНет
Индекс с методом доступа, отличным от btree и hashНет
Системный каталогНет
Родительская секционированная таблица или индекс без собственного физического храненияНет
Временное отношениеНе документируется как поддерживаемый сценарий

64.3.3.5. Неподдерживаемые объекты #

CSM не применяется к объектам, у которых нет подходящего физического хранения или поддерживаемого метода доступа.

К таким объектам относятся:

  • обычные представления;

  • последовательности;

  • внешние таблицы;

  • родительские секционированные таблицы и индексы без собственного физического хранения;

  • таблицы системных каталогов;

  • таблицы с методами доступа, отличными от heap;

  • материализованные представления, использующие методы доступа, отличные от heap;

  • индексы с методами доступа, отличными от btree и hash;

  • временные отношения в текущей реализации.

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

64.3.4. Параметры хранения #

CSM управляется двумя параметрами хранения объекта::

  • compression;

  • compression_page.

Эти параметры задаются в WITH (...) при создании поддерживаемого объекта или изменяются через ALTER ... SET (...) для уже существующего объекта.

64.3.4.1. compression #

Параметр compression задает алгоритм сжатия, который CSM использует для страниц relation.

compression = off | pglz | lz4 | zstd

Документируемые значения:

ЗначениеПоведение
offCSM отключен, используется стандартное хранение
pglzИспользуется встроенный алгоритм PostgreSQL PGLZ
lz4Используется LZ4
zstdИспользуется Zstandard

Значение по умолчанию: off.

Если compression = off, параметр compression_page не влияет на физическое хранение объекта.

64.3.4.2. compression_page #

Параметр compression_page задает размер страницы main fork, который CSM использует для хранения записей сжатых страниц.

compression_page = 1024 | 2048 | 4096

Значение по умолчанию: 4096.

Чем меньше compression_page, тем компактнее может быть main fork. Однако если запись сжатой страницы не помещается в выбранный размер, CSM использует overflow storage. Поэтому слишком маленькое значение может увеличить число обращений к overflow fork и снизить ожидаемый выигрыш.

64.3.4.3. Где задаются параметры #

Параметры CSM можно задавать при создании поддерживаемых объектов:

CREATE TABLE ... WITH (...);
CREATE INDEX ... WITH (...);
CREATE MATERIALIZED VIEW ... WITH (...) AS ...;

Для существующих объектов параметры можно изменить:

ALTER TABLE ... SET (...);
ALTER INDEX ... SET (...);
ALTER MATERIALIZED VIEW ... SET (...);

64.3.5. Как CSM хранит данные #

CSM находится между buffer manager и низкоуровневым файловым менеджером хранения. Общий путь можно представить так:

SQL команды
    |
Метод доступа к таблице / индексу
    |
Менеджер буферов
    |
Переключатель менеджера хранения
    |
    +-- стандартный менеджер хранения
    |
    +-- Compression Storage Manager
            |
            +-- основная вилка
            +-- форк переполнения
            +-- метаданные CSM
            +-- Кэши CSM

CSM хранит основную часть сжатой страницы в main fork. Если запись сжатой страницы не помещается в выбранный compression_page, оставшаяся часть размещается в overflow fork.

В обычном физическом хранении PostgreSQL relation может иметь несколько fork-файлов: например main, fsm, vm и init. CSM добавляет к этой схеме служебные fork-и и меняет содержимое main fork для CSM-объектов:

  • main fork хранит записи сжатых страниц. Размер такой записи определяется выбранным compression_page: 1024, 2048 или 4096 байт;

  • ctl fork хранит служебную информацию CSM, по которой менеджер хранения определяет, что relation использует CSM, а также какие параметры сжатия применяются;

  • overflow fork используется только для тех сжатых страниц, которые не помещаются в выбранный размер compression_page;

  • стандартные fork-и PostgreSQL, такие как fsm, vm и init, сохраняют свою обычную роль и не используются для размещения сжатого содержимого страниц.

Для верхних уровней PostgreSQL это различие прозрачно: table access method, index access method и buffer manager работают с обычными страницами PostgreSQL. Изменяется физическое представление этих страниц на диске.

Для relation также используется служебная информация CSM. Она нужна, чтобы менеджер хранения мог определить, какой способ хранения применен к объекту и с какими параметрами. Эта служебная информация является частью физического хранения объекта и должна сохраняться вместе с файлами relation при физическом резервном копировании, восстановлении и репликации.

При чтении CSM возвращает PostgreSQL обычную страницу. При записи CSM получает обычную страницу от PostgreSQL и решает, как сохранить ее на диске: в сжатом виде, с использованием overflow storage или без фактического уменьшения размера, если страница плохо сжимается.

При оценке физического размера CSM-объекта учитывайте, что экономия в main fork может сопровождаться появлением данных в overflow fork. Поэтому для анализа полезно смотреть не только общий размер relation, но и статистику overflow storage через pg_csm.

64.3.6. Выбор параметров сжатия #

Выбор параметров CSM зависит от данных и рабочей нагрузки. Универсального значения, которое одинаково хорошо подходит для всех таблиц и индексов, нет.

Рекомендуемый порядок выбора:

  1. Выберите таблицу, материализованное представление или индекс.

  2. Оцените сжимаемость на реальных данных.

  3. Сравните pglz, lz4 и zstd.

  4. Оцените, сколько страниц помещается в 1 KB, 2 KB и 4 KB после сжатия.

  5. Выберите compression.

  6. Выберите compression_page.

  7. Примените параметры.

  8. Для существующего объекта выполните физическую перезапись или перестроение, если это требуется.

  9. Сравните размер relation до и после.

  10. Проверьте поведение на реальной рабочей нагрузке.

64.3.6.1. Как выбирать compression #

Используйте off, если relation небольшая, данные плохо сжимаются, важна минимальная CPU-нагрузка или требуется стандартное физическое хранение.

Используйте pglz, если нужен встроенный алгоритм PostgreSQL и предсказуемое поведение без ориентации на максимальный коэффициент сжатия.

Используйте lz4, если важны скорость сжатия и распаковки, а также низкая задержка. Обычно это хороший кандидат для нагрузок с преобладанием чтения или смешанных нагрузок, где нужен баланс между экономией места и затратами CPU.

Используйте zstd, если главная цель - максимальная экономия диска и ввода-вывода, а рабочая нагрузка допускает дополнительные затраты CPU. Обычно zstd стоит проверять на больших relation, где потенциальный выигрыш по размеру заметен.

64.3.6.2. Как выбирать compression_page #

1024 стоит рассматривать, если большинство страниц после сжатия помещается в 1 KB. Это значение может дать максимальную экономию main fork, но увеличивает риск overflow для страниц, которые сжимаются хуже.

2048 подходит как промежуточный вариант, если заметная часть страниц не помещается в 1 KB, но помещается в 2 KB.

4096 является значением по умолчанию. Это наиболее осторожный выбор, если данные сжимаются умеренно или предварительный анализ еще не выполнен.

64.3.6.3. Связь с pg_csm #

Для предварительной оценки используйте расширение pg_csm. Оно не включает CSM и не меняет физическое хранение relation, а помогает заранее понять, какой эффект можно ожидать от разных алгоритмов и значений compression_page.

Основная функция для выбора параметров - csm_compress_analysis. Она читает страницы relation, сжимает их во временном буфере и возвращает статистику по алгоритмам. При выборе compression и compression_page в первую очередь смотрите на:

  • avg_compress - средний коэффициент сжатия;

  • avg_page_sz - средний размер страницы после сжатия;

  • pages_over_1k, pages_over_2k, pages_over_4k - сколько страниц не помещается в соответствующий размер.

Например, если для выбранного алгоритма почти все страницы помещаются в 2 KB, значение compression_page = 2048 может быть хорошим компромиссом. Если много страниц попадает в pages_over_2k или pages_over_4k, стоит рассмотреть 4096 либо другой алгоритм, чтобы уменьшить использование overflow storage.

После включения CSM расширение pg_csm также можно использовать для проверки результата: smgr_info показывает, какой storage manager и какие параметры использует relation, а csm_overflow_fork_stat помогает оценить фактическое использование overflow fork. Статистика кешей CSM относится скорее к диагностике эксплуатации, чем к первоначальному выбору параметров.

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

64.3.7. Изменение параметров существующих объектов #

Изменение параметров хранения определяет, как объект должен храниться дальше. Для уже существующих данных важно понимать, требуется ли физическая перезапись объекта.

64.3.7.1. ALTER TABLE ... SET (...) #

Для таблиц изменение compression или compression_page может приводить к физической перезаписи объекта, если новые параметры CSM отличаются от прежних.

ALTER TABLE events
SET (
    compression = zstd,
    compression_page = 1024
);

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

64.3.7.2. ALTER INDEX ... SET (...) #

Для индексов изменение параметров CSM может требовать перестроения индекса.

ALTER INDEX events_created_at_idx
SET (
    compression = zstd,
    compression_page = 2048
);

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

64.3.7.3. ALTER MATERIALIZED VIEW ... SET (...) #

Для материализованных представлений, использующих heap-хранение, изменение параметров CSM рассматривается аналогично heap-таблицам: чтобы применить новые параметры к существующему физическому содержимому, может потребоваться физическая перезапись.

ALTER MATERIALIZED VIEW recent_events
SET (
    compression = zstd,
    compression_page = 2048
);

После физической перезаписи страницы материализованного представления записываются с актуальными параметрами CSM.

64.3.8. Производительность и обслуживание #

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

Эффект зависит от:

  • тип данных и форма;

  • размера relation;

  • выбранного алгоритма;

  • значения compression_page;

  • доли страниц, попадающих в overflow storage;

  • соотношения операций чтения и записи;

  • характеристик CPU и хранилища.

Нагрузка с преобладанием чтения может выиграть за счет уменьшения ввода-вывода, особенно если relation хорошо сжимается. Нагрузка с большим числом записей может сильнее ощущать стоимость сжатия. Для систем, чувствительных к задержкам, обязательно проверяйте CSM на реальной нагрузке.

64.3.8.1. Операции обслуживания #

VACUUM обслуживает relation обычным образом. Специальное пользовательское поведение VACUUM для полного пересжатия страниц не документируется. Если нужно полностью применить новые параметры к таблице, используйте операцию, которая физически переписывает объект.

VACUUM FULL физически переписывает таблицу и может использоваться как способ полностью записать таблицу с текущими параметрами хранения.

CLUSTER физически переписывает таблицу в порядке выбранного индекса и может применить текущие параметры хранения к переписанному объекту.

REINDEX перестраивает индекс и может использоваться, чтобы получить индекс, записанный с текущими параметрами CSM.

TRUNCATE удаляет содержимое relation. Новые страницы после TRUNCATE записываются с текущими параметрами хранения объекта.

64.3.8.2. Резервное копирование, восстановление и репликация #

Физическое резервное копирование и физическая репликация должны сохранять все физические файлы relation, включая служебные fork-файлы CSM. Это часть физического состояния объекта.

Логическое резервное копирование и восстановление воспроизводят объекты через DDL. Поэтому для CSM важно, чтобы DDL содержал нужные параметры хранения, а принимающая сторона поддерживала CSM и выбранные алгоритмы.

Логическая репликация передает данные логически. Физическое хранение на подписчике определяется DDL, настройками и возможностями подписчика.

64.3.9. Конфигурация #

CSM использует серверные параметры для настройки кэшей менеджера хранения. Эти кэши размещаются в shared memory и инициализируются при запуске сервера, поэтому изменение параметров требует перезапуска.

64.3.9.1. ctl_cache_slots #

ctl_cache_slots задает количество элементов в кэше служебной информации менеджера хранения.

Значение по умолчанию: 4096.

Минимальное значение: 128.

Увеличение значения может быть полезно, если в системе одновременно активно используется много relation с CSM или часто открываются разные объекты.

64.3.9.2. ovr_cache_slots #

ovr_cache_slots задает количество элементов в кэшах и служебных структурах, связанных с overflow storage CSM.

Значение по умолчанию: 64.

Минимальное значение: 8

Увеличение значения может быть полезно, если рабочая нагрузка активно работает с relation, у которых много страниц попадает в overflow storage.

64.3.10. Диагностика #

Для диагностики и предварительной оценки используйте расширение pg_csm. Его следует рассматривать как основной пользовательский инструмент анализа CSM.

Типовые диагностические задачи:

  • понять, использует ли relation CSM;

  • оценить потенциальный размер страниц после сжатия;

  • сравнить pglz, lz4 и zstd;

  • оценить риск overflow для compression_page = 1024, 2048 и 4096;

  • проверить эффект после физической перезаписи или REINDEX;

  • сравнить размер relation до и после включения CSM.

Подробное описание функций pg_csm не включается в эту страницу. См. документацию расширения pg_csm.

64.3.11. Ограничения #

CSM работает на уровне физического хранения relation и поддерживается только для ограниченного набора объектов. Перед включением CSM учитывайте следующие ограничения текущей реализации.

Предупреждение

Некоторые ограничения связаны с расширениями и утилитами, которые работают с методами доступа или читают физические файлы relation напрямую и не разбирают CSM-формат. Эти ограничения не означают, что CSM-объекты нельзя резервировать или обслуживать. Они предупреждают о сценариях, в которых диагностика повреждений или совместимость с другими механизмами хранения может отличаться от поведения стандартных объектов PostgreSQL. Поддержка таких сценариев может быть улучшена в будущих версиях.

  • CSM не заменяет TOAST.

  • CSM не является сжатием на уровне столбцов.

  • CSM не является table access method.

  • CSM применяется только к поддерживаемым типам relation и методам доступа.

  • CSM не применяется к системным каталогам.

  • Временные отношения не документируются как поддерживаемый сценарий CSM.

  • Не все методы доступа индексов поддерживают CSM.

  • compression = off отключает CSM.

  • compression_page используется только когда compression не равен off.

  • Малое значение compression_page может увеличить использование overflow storage.

  • Эффективность зависит от данных и рабочей нагрузки.

  • Экономия диска может сопровождаться ростом CPU-нагрузки.

  • Перед включением CSM для важных рабочих объектов рекомендуется проверять эффект на репрезентативной нагрузке.

64.3.11.1. Расширения #

64.3.11.1.1. page_repair #

Функция pg_repair_page не предназначена для восстановления страниц, которые хранятся в CSM-формате. CSM использует собственное физическое представление страниц и служебные fork-файлы, поэтому инструмент, рассчитанный на стандартные страницы PostgreSQL, не может корректно восстановить поврежденную сжатую страницу.

При попытке восстановить поврежденную сжатую страницу возвращается ошибка:

ERROR:  csm checksum verification failed in file "base/..."

Кроме того, pg_repair_page не распознает служебные fork-файлы CSM: ctl и ovr. При попытке передать такой fork-файл в качестве аргумента возвращается ошибка:

ERROR:  invalid fork name
HINT:  Valid fork names are "main", "fsm", "vm", and "init".

Это ожидаемое поведение: pg_repair_page поддерживает только стандартные fork-файлы PostgreSQL и не предназначена для работы с CSM-специфичными fork-файлами. До появления поддержки CSM-формата в инструментах восстановления pg_repair_page не следует рассматривать как средство ремонта CSM-страниц.

64.3.11.1.2. pg_tde #

CSM-сжатие и шифрование через pg_tde нельзя использовать одновременно для одного объекта. CSM поддерживает только стандартный метод доступа heap, поэтому любая попытка совместить параметры сжатия с методом доступа tde_heap завершается ошибкой.

Ошибка возникает во всех трех сценариях:

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

CREATE TABLE test_enc (id SERIAL, PRIMARY KEY (id))
    USING tde_heap WITH (compression = zstd);
ERROR:  Compression storage manager is not supported for table access method "tde_heap"
DETAIL:  Compression storage manager supports only the heap access method.

При установке параметров сжатия на существующей tde_heap-таблице:

CREATE TABLE test_enc (id SERIAL, PRIMARY KEY (id))
    USING tde_heap;
ALTER TABLE test_enc SET (compression = zstd);
ERROR:  Compression storage manager is not supported for table access method "tde_heap"
DETAIL:  Compression storage manager supports only the heap access method.

При смене метода доступа с heap на tde_heap для таблицы со сжатием:

CREATE TABLE test_enc (id SERIAL, PRIMARY KEY (id))
    WITH (compression = zstd);
ALTER TABLE test_enc SET ACCESS METHOD tde_heap;
ERROR:  Compression storage manager is not supported for table access method "tde_heap"
DETAIL:  Compression storage manager supports only the heap access method.

При необходимости используйте один из подходов:

  • только шифрование: USING tde_heap без параметров CSM;

  • только сжатие: стандартный heap с WITH (compression = zstd) и без pg_tde.

64.3.11.2. Утилиты #

64.3.11.2.1. pg_basebackup #

При создании резервной копии кластера, содержащего CSM-таблицы с поврежденными сжатыми страницами, pg_basebackup не всегда диагностирует повреждение так же, как для стандартных 8 KB страниц PostgreSQL.

Вместо ожидаемой ошибки контрольной суммы:

WARNING:  checksum verification failed in file "./base/5/16384", block 404: calculated 223C but expected 4F0
pg_basebackup: error: checksum error occurred

утилита может вывести предупреждение о несоответствии размеров буфера и завершиться успешно:

WARNING:  could not verify checksum in file "./base/5/16384", block 32: read buffer size 1 and page size 8192 differ

Это связано с тем, что CSM хранит страницы в физическом формате, отличном от стандартного формата PostgreSQL: размер блока в main fork может не совпадать с размером обычной страницы PostgreSQL. pg_basebackup не разбирает CSM-структуры и не может корректно интерпретировать такие блоки при проверке контрольных сумм.

До появления поддержки CSM-формата в pg_basebackup не следует полагаться на проверку контрольных сумм этой утилиты как на надежный способ обнаружения повреждений в CSM-таблицах. При резервном копировании кластеров с CSM-таблицами учитывайте, что результат проверки контрольных сумм для таких relation может быть недостоверным.

64.3.11.2.2. pg_checksums #

При проверке контрольных сумм кластера, содержащего CSM-таблицы, pg_checksums может завершиться с ошибкой чтения вместо сообщения о повреждении страницы. Утилита пытается прочитать служебный fork _ctl как стандартную 8192-байтную страницу, но размер этого fork-файла отличается от ожидаемого:

ERROR: could not read block 0 in file "$PGDATA/base/5/16388_ctl": read 32 of 8192

В результате pg_checksums не выводит ожидаемую диагностику о несовпадении контрольных сумм и не учитывает поврежденный блок в счетчике Bad checksums.

До появления поддержки CSM-специфичных fork-файлов и формата хранения CSM-страниц pg_checksums не следует рассматривать как надежное средство проверки целостности CSM-таблиц.

64.3.12. Примеры #

64.3.12.1. Создание таблицы со сжатием #

CREATE TABLE events (
    id bigint,
    created_at timestamptz,
    payload jsonb
) WITH (
    compression = zstd,
    compression_page = 2048
);

64.3.12.2. Создание индекса со сжатием #

CREATE INDEX events_created_at_idx
ON events USING btree (created_at)
WITH (
    compression = lz4,
    compression_page = 2048
);

64.3.12.3. Изменение параметров таблицы #

ALTER TABLE events
SET (
    compression = zstd,
    compression_page = 1024
);

После изменения параметров проверьте, была ли выполнена физическая перезапись объекта, если важно применить новые параметры ко всем уже существующим данным.

64.3.12.4. Изменение параметров индекса #

ALTER INDEX events_created_at_idx
SET (
    compression = zstd,
    compression_page = 2048
);

Чтобы полностью применить новые параметры к существующему индексу, используйте сценарий перестроения или REINDEX, предусмотренный для вашей версии продукта.

64.3.12.5. Типовой сценарий выбора параметров #

  1. Найдите крупную таблицу или индекс, для которых важен размер на диске.

  2. Сравните pglz, lz4 и zstd.

  3. Сравните pglz, lz4 и zstd.

  4. Оцените, сколько страниц попадет в overflow при разных значениях compression_page.

  5. Выберите параметры и примените их к тестовой копии объекта.

  6. Выполните физическую перезапись или REINDEX.

  7. Сравните размер relation.

  8. Проверьте задержки, CPU и ввод-вывод на реальной нагрузке.

  9. После проверки примените параметры к рабочему объекту.