31.2. Как сжатие интегрируется в Postgres Pro Enterprise

Для увеличения эффективности дискового ввода/вывода Postgres Pro Enterprise обращается к файлам через менеджер буферов, который способен закреплять в памяти наиболее часто используемые страницы. Каждая страница имеет фиксированный размер (по умолчанию 8 КБ). Но если мы сжимаем страницу, её размер будет зависеть от её содержимого. Поэтому изменённая страница может занимать больше (или меньше) места, чем исходная. А следовательно, мы не всегда можем заменить содержимое страницы на диске. Вместо этого мы должны найти для неё новое место и как-то высвободить старое. К решению этой проблемы есть два основных подхода:

Выделение места

Мы должны реализовать собственный механизм выделения места в файле. Обычно для уменьшения дефрагментации место выделяется блоками фиксированного размера. Это означает, что мы выделяем место некоторыми фиксированными порциями. Например, если размер сжатой страницы 932 байта, мы выделим для неё в файле 1024 байта.

Сборка мусора

Мы можем всегда выделять место для страниц в конце файла и периодически делать файл компактнее (дефрагментировать его), перемещая все использованные страницы в начало файла. Такую процедуру сборки мусора можно производить в фоновом режиме. Как уже объяснялось в предыдущем разделе, при последовательной записи на диск сбрасываемых страниц может значительно возрасти скорость и общая производительность. Вот почему мы использовали этот подход в CFS.

Поскольку расположение страницы нефиксированное и страница может перемещаться, мы больше не можем обращаться к странице по её адресу и должны использовать дополнительный уровень адресации, чтобы перейти от логического адреса страницы к её физическому расположению на диске. Это осуществляется с помощью файлов отображения. В большинстве случаев такое отображение будет умещаться в памяти (размер отображения в 1000 раз меньше размера файла данных) и трансляция адресов практически никак не отражается на времени обращения к странице. Но у нас возникает необходимость обслуживать эти дополнительные файлы: сбрасывать их на диск во время контрольных точек, удалять при удалении таблицы, включать в резервную копию и так далее...

Postgres Pro Enterprise хранит отношение в наборе файлов, ограничивая размер каждого 2 гигабайтами. CFS создаёт для каждого файла отдельную карту отображения страниц и производит сборку мусора в нескольких фоновых процессах. Число этих рабочих процессов и условия простоя в их работе может настраиваться администратором баз данных. Эти рабочие процессы разделяют свою работу по хешу дескриптора файла (inode), так что конфликт между ними исключён. Обрабатывается каждый файл независимо. Эти файлы могут блокироваться в момент сборки мусора, но всё отношение при этом не блокируется. Для сохранения целостности данных сборщик мусора создаёт копии исходного файла с данными и файла отображения, а когда данные полностью сохраняются на диске, новая версия файла данных атомарно переименовывается и получает исходное имя. Затем новая карта отображения копируется в файл, отображённый в память, и предыдущий файл отображения удаляется. Производя восстановление после сбоя, мы сначала проверяем, нет ли на диске резервной копии файла данных. Если такой файл существует, это означает, что исходный файл ещё не заменился и мы можем безопасно удалить копию. Если же такого файла нет, мы проверяем наличие копии файла отображения. Если эта копия находится, значит дефрагментация не была завершена из-за сбоя, и мы можем продолжить эту операцию, скопировав отображение из копии.

По умолчанию CFS использует библиотеку сжатия zstd. Из соображений безопасности CFS проверяет, соответствует ли алгоритм, используемый в табличном пространстве, этой библиотеке.