Сравнение реализаций сжатия данных в InnoDB и PgPro Enterprise

Сравнение реализаций сжатия данных в InnoDB и PgPro Enterprise

Alexey Kopytov

Компрессия в InnoDB

На самом деле, их два вида, мы сейчас рассмотрим table compression, а про page compression как-нибудь в другой раз.

При использовании table compression на диске хранятся только сжатые данные, индексы и никакой дополнительной служебной информации. При считывании в buffer pool страница расжимается, но в памяти остаётся как несжатая, так и сжатая копия. Чтение делается из несжатой копии, а запись происходит в обе копии. При этом запись в сжатую копию оптимизируется: чтобы не пережимать страницу на каждое обновление, в конце страницы есть служебная область под названием modification log. Туда сначала дописываются несжатые операции обновления/вставки. Страница пережимается с объединением записей в modification log в двух случаях: 1) если modification log переполнился и 2) если страницу нужно сбросить на диск. Если после объединения modification log сжатый образ страницы оказывается больше размера блока, делается стандартное разбиение индексной страницы (page split).

Если из buffer pool нужно удалить страницу, чтобы освободить место для новых, сначала просто удаляются несжатые версии страниц. А когда таких не осталось, сбрасываются на диск сжатые версии. Сжатые страницы сбрасываются на те же места файла, где были изначально (если не было разбиений и перестроения индексного дерева).

Важная деталь: сжимаются на самом деле не страницы целиком, а только отдельные записи на них. Служебные заголовки не сжимаются. Это позволяет, например, удалить запись без пережатия страницы, просто пометив её как удалённую в заголовке.

Компрессия в PgPro Enterprise

Документация достаточно куцая, а доступа к коду нет, но некоторые вещи понять можно. Данные хранятся на диске в сжатом виде. При считывании в память страницы разжимаются, но по факту страница существует в памяти тоже в двух вариантах: несжатом в shared buffers и сжатом в page cache. Обновления идут только в несжатую версию. Пережимается страница при сбросе на диск, но т.к. размер её может измениться после обновлений, она дописывается не на своё место, а в конец файла. Но т.к. она теперь оказывается не на своём месте, нужно как-то запомнить где кто лежит. Для этого на диске создаётся ещё один файл с картой отображения логических и физических локаций, который тоже нужно держать в памяти и работать с данными через ещё одну прослойку адресации. Кроме того, у файлов начинает вырастать хвост в виде дописываемых в конец обновлений. С которым нужно что-то делать, и этим занимается сборщик мусора.

Сборщик мусора периодически просыпается, проходит по файлам данных, и если мусора стало слишком много, производит "дефрагментацию", блокируя при этом файлы для пользовательских запросов и VACUUM на время сборки мусора. То есть, сегменты таблицы по 2GB, где накопилось достаточно обновлений, будут заблокированы на неопределённое время. В лабораторных условиях на pgbench всё может выглядеть не так страшно, но на практике это означает непредсказуемые всплески latency, величина и частота которых очень зависит от нагрузки и железа. Даже если повезёт, и сборка мусора не будет блокировать текущие запросы, она всё равно будет отнимать на себя дополнительные ресурсы по IO и CPU. А настройка работы сборщика мусора становится ответственностью DBA. Также утилитам для физического резервного копирования нужно знать про дополнительные файлы на диске, которые тоже нужно включить в резервную копию.

Плюсы, минусы, подводные камни

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

Единственный плюс, который я вижу в подходе PgPro EE, заключается в том, что реализация достаточно простая и "сбоку", т.е. без серьёзных изменений существующего кода PostgreSQL. Минусы в том, что 1) файлы данных начинают распухать (у Постгреса с этим и так всё печально) 2) появляется дополнительные фоновые процессы для сборки мусора, которые потребляют ресурсы, блокируют файлы и которые нужно настраивать и 3) файлы отображений на диске, которые нужно хранить также и в памяти и не забыть скопировать в резервную копию. Более детальный анализ можно было бы провести, посмотрев в код (мне, например, интересно, что происходит при удалении/добавлении/обновлении записей), но кода нет. Да и самой функции для большинства пользователей Постгрес тоже нет. Enterprise он такой, не для всех :-)

Ссылки

 - табличная компрессия в InnoDB: https://dev.mysql.com/doc/refman/en/innodb-compression-internals.html

 - то же, но с картинками:  https://www.slideshare.net/nizameddin/getting-innodb-compressionreadyforfacebookscale

 - описание компрессии в PgPro Enterprise: https://postgrespro.ru/docs/enterprise/10/cfs-implementation


Report Page