34.3. Использование сжатия #

Сжатие можно включить только для отдельных табличных пространств. Чтобы сделать табличное пространство сжимаемым, нужно установить параметр compression при создании этого пространства. Например:

    postgres=# CREATE TABLESPACE tcfs LOCATION '/var/data/cfs' WITH (compression=true);
  

Все таблицы, создаваемые в этом табличном пространстве, будут сжиматься с использованием применяемого по умолчанию алгоритма zstd.

Помимо логического значения для этого параметра вы можете явно указать библиотеку, которая будет использоваться для сжатия. Возможные варианты: zstd, default (действует так же, как zstd), pglz, zlib и lz4. Например, чтобы использовать zlib, создайте табличное пространство так:

    postgres=# CREATE TABLESPACE tcfs1 LOCATION '/var/data/cfs1' WITH (compression='zlib');
  

Заданные при создании табличного пространства параметры сжатия изменить нельзя, в частности, невозможно сделать ранее сжатое пространство несжатым и наоборот. Хотя пользовательские отношения в CFS всегда сжимаются, этого не происходит с системными отношениями, если числовая часть имени файла, например, pg_relation_filenode(), меньше 16384 (за дополнительной информацией обратитесь к Таблице 9.98).

Если вы хотите, чтобы сжимались все таблицы, создаваемые в текущем сеансе, вы можете сделать сжатое табличное пространство пространством по умолчанию, как описано в Разделе 22.6.

Примечание

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

Для настройки CFS используйте параметры, описанные в Разделе 19.15. По умолчанию CFS запускает для сборки мусора один рабочий процесс. Сборщик мусора проходит по каталогу табличного пространства, находит в нём файлы отображений и проверяет в них процент мусора. Если отношение неиспользуемого объёма к общему превышает значение cfs_gc_threshold, этот файл дефрагментируется. На время дефрагментации файл блокируется, в результате чего ни к какой его части нельзя обратиться. Чтобы избежать зависания в случае ошибки при сборке мусора, CFS ждёт снятия блокировки с файла cfs_gc_respond_time секунд. Если блокировка не снимается, в журнал записывается предупреждение. По завершении дефрагментации сборщик мусора ждёт cfs_gc_delay миллисекунд и продолжает проход по каталогу. Завершив проход, он ждёт дополнительно cfs_gc_period миллисекунд и начинает новый проход. Если для CFS настроено несколько процессов сборки мусора, они разделяют свою работу по хешу дескриптора файла (inode).

Миграция больших сжатых таблиц может занимать много времени. Для ускорения миграции установите для параметра cfs_compression значение off, чтобы временно отключить сжатие CFS. После завершения миграции включите его обратно.

Несколько функций позволяют рассчитать объём, который занимают на диске различные объекты в CFS. Например:

  • pg_relation_size() вычисляет объём, который занимает на диске отношение в CFS.

  • pg_total_relation_size() вычисляет общий объём, который занимает на диске указанная таблица в CFS с учётом всех индексов и данных TOAST.

  • pg_indexes_size() вычисляет общий объём, который занимают на диске индексы, связанные с указанной таблицей, в CFS.

  • pg_database_size() вычисляет объём, который занимает на диске указанная база данных в CFS.

За дополнительной информацией обратитесь к Подразделу 9.27.7.

CFS предоставляет различные функции для ручного управления сборкой мусора CFS и получения информации о состоянии и активности CFS. Полный список функций вы можете найти в Подразделе 9.27.11.

Чтобы запустить сборку мусора вручную, воспользуйтесь функцией cfs_start_gc(n_workers). Эта функция возвращает число рабочих процессов, которые были фактически запущены. Если значение параметра cfs_gc_workers отлично от нуля, сборка мусора выполняется в фоне и функция cfs_start_gc ничего не делает, а просто возвращает 0.

Как и процедура автоматического сбора мусора, функция cfs_start_gc(n_workers) обрабатывает только те отношения, в которых процент мусорных блоков превосходит значение cfs_gc_threshold. Если вам нужно дефрагментировать отношение с меньшим процентом мусора, вы можете временно задать для этого параметра меньшее значение в текущем сеансе до вызова этой функции.

Коэффициент сжатия таблицы можно предварительно оценить с помощью cfs_estimate(relation). Эта функция считывает первые десять процентов блоков отношения (но не более 100 блоков), сжимает их и возвращает средний коэффициент сжатия. Так, если она возвращает значение 7.8, это означает, что сжатая таблица будет занимать почти в 8 раз меньше места, чем исходная. Расчёт производится для всех доступных алгоритмов сжатия.

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

Функцию cfs_estimate(relation) следует использовать только после контрольной точки, чтобы избежать некорректных оценок.

Функция cfs_compression_ratio(relation) позволяет проверить, насколько точной была оценка, выданная функцией cfs_estimate(relation). Она возвращает фактический коэффициент сжатия для всех сегментов сжатого отношения. Коэффициент сжатия рассчитывается как результат деления общей суммы виртуальных размеров всех сегментов отношения (числа блоков, умноженного на 8 Кбайт) на сумму физических размеров его файлов сегментов. Для несжатых отношений функция возвращает значение NaN.

Как было сказано ранее, CFS всегда добавляет изменённые строки в конец сжатого файла. Поэтому физический размер файла может быть больше объёма полезных данных в нём. Другими словами, файл CFS становится фрагментированным и поэтому сборщик мусора CFS периодически проводит в нём дефрагментацию. Функция cfs_fragmentation(relation) возвращает средний коэффициент фрагментации файлов отношения. Этот коэффициент вычисляется как результат деления суммы физических размеров файлов минус используемый объём в этих файлах на сумму физических размеров данных файлов.

Чтобы произвести дефрагментацию определённого сжатого отношения, воспользуйтесь функцией cfs_gc_relation(отношение). Она возвратит количество обработанных сегментов в данном отношении. Так же как и фоновая процедура сборки мусора, эта функция обрабатывает только те сегменты, в которых процент мусорных блоков превышает значение cfs_gc_threshold.

Для наблюдения за активностью, связанной со сборкой мусора, предлагаются следующие функции: cfs_gc_activity_scanned_files (возвращает число файлов, просканированных при сборке мусора), cfs_gc_activity_processed_files (возвращает число файлов, сжатых при сборке мусора), cfs_gc_activity_processed_pages (возвращает число страниц, перемещённых сборщиком мусора в процессе дефрагментации файлов) и cfs_gc_activity_processed_bytes (возвращает общий объём перемещённых страниц). Все эти функции подсчитывают значения с момента запуска системы.

34.3. Using Compression #

Compression can only be enabled for separate tablespaces. To compress a tablespace, you should enable the compression option when creating this tablespace. For example:

    postgres=# CREATE TABLESPACE tcfs LOCATION '/var/data/cfs' WITH (compression=true);
  

All tables created in this tablespace will be compressed using zstd, which is the default compression library.

Aside from the boolean value of the option, you can explicitly specify the library to use for compression. Possible values are zstd, default (the same as zstd), pglz, zlib, and lz4. For example, to use zlib, create the tablespace as follows:

    postgres=# CREATE TABLESPACE tcfs1 LOCATION '/var/data/cfs1' WITH (compression='zlib');
  

Once set, the tablespace compression option cannot be altered, so you cannot compress or decompress an already existing tablespace. While user relations are always compressed in CFS, system relations are not compressed if the numeric part of the filename, such as, for example, pg_relation_filenode(), is less than 16384 (see Table 9.98 for more details).

If you would like to compress all tables created within the current session, you can make the compressed tablespace your default tablespace, as explained in Section 22.6.

Note

For compressed tablespaces, pg_checksums and pg_basebackup will not verify checksums even if they are enabled.

To configure CFS, use configuration parameters listed in Section 19.15. By default, CFS launches one background worker performing garbage collection. Garbage collector traverses tablespace directory, locating map files in it and checking percent of garbage in this file. When ratio of used and allocated spaces exceeds cfs_gc_threshold threshold, this file is defragmented. The file is locked at the period of defragmentation, preventing any access to this part of relation. To avoid getting stuck during any file defragmentation failure, CFS waits cfs_gc_respond_time seconds before the file is released from the lock. If it is not, a warning is written to the log. When defragmentation is completed, garbage collection waits cfs_gc_delay milliseconds and continues directory traversal. After the end of traversal, GC waits cfs_gc_period milliseconds and starts new GC iteration. If there are more than one GC workers, then they split work based on hash of file inode.

Migrating large compressed tables might take a long time. To speed up data migration, set the cfs_compression parameter to off to temporarily disable CFS compression. After migration is completed, enable it back.

Several functions allow you to calculate the disk space used by different objects in CFS. For example:

  • pg_relation_size() can compute the disk space used by the relation in CFS.

  • pg_total_relation_size() computes the total disk space used by the specified table in CFS, including all indexes and TOAST data.

  • pg_indexes_size() computes the total disk space used by indexes attached to the specified table in CFS.

  • pg_database_size() computes the disk space used by the specified database in CFS.

See Section 9.27.7 for more details.

CFS provides several functions to manually control CFS garbage collection and get information on CFS state and activity. For the full list of functions, see Section 9.27.11.

To initiate garbage collection manually, use the cfs_start_gc(n_workers) function. This function returns the number of workers, which are actually started. If the cfs_gc_workers parameter is non-zero, then GC is performed in background and the cfs_start_gc function does nothing and returns 0.

Like the automatic garbage collection, the cfs_start_gc(n_workers) function only processes relations if the percent of garbage blocks in this relation exceeds the cfs_gc_threshold value. To defragment a relation with a smaller percent of garbage, you can temporarily set this parameter to a smaller value for your current session before calling this function.

The table compression ratio can be estimated using the cfs_estimate(relation) function. This function takes the first ten percent of relation blocks (but no more than 100 blocks), compresses them, and returns the average compression ratio. For example, a value of 7.8 indicates that the compressed table will occupy about eight times less space than the original. The calculation is performed for all available compression algorithms.

Warning

cfs_estimate(relation) should be used only after a checkpoint to avoid incorrect estimations.

The cfs_compression_ratio(relation) function allows you to check how precise was the estimation of the cfs_estimate(relation) function. It returns real compression ratio for all segments of the compressed relation. Compression ratio is total sum of virtual size of all relation segments (number of blocks multiplied by 8kb) divided by sum of physical size of the segment files. For uncompressed relations, the function returns NaN.

As it was mentioned before, CFS always appends updated blocks to the end of the compressed file. So physical size of the file can be greater than used size in this file. I.e. CFS file is fragmented and defragmentation is periodically performed by CFS garbage collector. The cfs_fragmentation(relation) function returns the average fragmentation of relation files. It is calculated as sum of physical sizes of the files minus sum of used size of the files divided by sum of physical sizes of the files.

To perform defragmentation for a particular compressed relation, use the cfs_gc_relation(relation) function. It returns the number of processed segments of the relation. Just like garbage collection performed in the background, this function only processes segments in which the percent of garbage blocks exceeds the cfs_gc_threshold value.

There are several functions allowing to monitor garbage collection activity: cfs_gc_activity_scanned_files returns the number of files scanned by GC, cfs_gc_activity_processed_files returns the number of file compacted by GC, cfs_gc_activity_processed_pages returns the number of pages transferred by GC during files defragmentation, cfs_gc_activity_processed_bytes returns the total size of transferred pages. All these functions calculate their values since system start.

FAQ