Статьи

Сжатие данных в InnoDB для текстовых и блоб-полей

 Это сообщение от Майкла Кобурна  из MySQL Performance Blog. 

Вы хотели сжать только определенные типы столбцов в таблице, оставив другие столбцы без сжатия? Работая над делом клиента на этой неделе, я увидел интересную проблему, когда в таблице было много сильно используемых полей TEXT с некоторыми запросами на чтение, превышающими 500 МБ (!!), и сохраненными в таблице размером 100 ГБ. В этом случае нам не разрешалось вносить какие-либо изменения в логику запросов или приложений, поэтому мы решили реализовать формат файла Barracuda и использовать сжатые строки, поскольку это привлекло меня для этого приложения, предназначенного для чтения. Один быстрый способ узнать, выиграют ли ваши строки от сжатия, — это прочитать сообщение в блоге Петра Зайцева и выполнить:

SELECT AVG(LENGTH((`colTextField`)) FROM `t1` WHERE `id` < 1000

сравните это с:

SELECT AVG(LENGTH(COMPRESS(`colTextField`))) FROM `t1` WHERE `id` < 1000

В нашем случае мы увидели сокращение на 75%, когда поле TEXT было сжато, что, как мы чувствовали, указывало бы на выгоду, получаемую от сжатия таблицы.

С исходным форматом файла InnoDB Antelope у вас есть выбор ROW_FORMAT = COMPACT и ROW_FORMAT = REDUNDANT, где InnoDB хранит первые 768 байтов столбцов переменной длины (BLOB, VARCHAR, TEXT) в записи индекса, а остаток хранится на страницах переполнения.  COMPACT  стал по умолчанию после MySQL 5.0.3 и имеет более компактное представление для нулевых значений и полей переменной длины, чем REDUNDANT .

Используя новый формат файла Barracuda InnoDB (доступный с плагином InnoDB 1.1 или MySQL 5.5), теперь вы можете использовать сжатие таблиц , указав ROW_FORMAT = COMPRESSED . В нашем случае мы только хотели, чтобы MySQL пытался переместить большие (более 16 КБ) поля TEXT за пределы страницы, поэтому мы использовали KEY_BLOCK_SIZE = 16директивы. Это означает, что каждое поле TEXT / BLOB, которое превышает 16 КБ, будет сохранено на своей собственной странице (за исключением 20-байтового указателя, хранящегося на странице индекса). Согласно нашему анализу, 75% BLOB-объектов, хранящихся в таблице, имели размер более 8 КБ, что обеспечивало 90% использования пространства, поэтому сжатие только хранимых извне BLOB-объектов обеспечивало существенные преимущества. Почему мы выбрали KEY_BLOCK_SIZE, который равен значению размера страницы InnoDB 16 КБ? Как говорится в прекрасном руководстве по MySQL :

Эта установка может все еще быть полезной для таблиц со многими долго  BLOBVARCHAR или  TEXT столбцами, поскольку такие ценности часто делают компресс хорошо, и , следовательно , могут потребоваться меньше «переполнение» страницы.

Я не проводил тестирование с меньшим значением KEY_BLOCK_SIZE, поскольку у нас было минимальное время для изменения сжатия таблицы (учитывая длительное время выполнения ALTER TABLE), вы можете найти преимущества для своего приложения из другого значения KEY_BLOCK_SIZE. Также обратите внимание, что вам нужно включить   динамическую  переменную  innodb_file_format = BARRACUDA  (не забудьте установить ее в my.cnf!):

SET GLOBAL innodb_file_format=BARRACUDA;

Одно предостережение: вы должны работать с innodb_file_per_table = 1, поскольку системное табличное пространство InnoDB не может быть сжато, см. Эту страницу для получения дополнительной информации о том, как включить сжатие для таблицы .

Чтобы использовать таблицы формата Barracuda, вам необходимо создать их новые и перенести данные или повлиять на существующие таблицы с помощью инструкции ALTER TABLE. Поскольку сжатие таблицы зависит от таблицы, директивы ROW_FORMAT и KEY_BLOCK_SIZE передаются через операторы CREATE TABLE или ALTER TABLE. В нашем случае мы решили пересоздать таблицу с помощью ALTER TABLE с помощью нулевой операции, подобной этой:

ALTER TABLE `t1` ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16;

В нашем случае, несмотря на то, что у клиента был 24-ядерный компьютер с частотой 3GHz, ALTER TABLE медленно развивался, поскольку при сжатии данных он был связан с одним процессором. Просто наберитесь терпения. :)Помните также, что если вы начали с таблицы объемом 100 ГБ и предполагали, что знаете приблизительную степень сжатия, у вас останется значительно меньший объем дискового пространства, поэтому в идеале вы сможете отложить покупку дополнительного дискового пространства.

Так каков был реальный результат этого упражнения? Мы смогли продемонстрировать 70% -ное улучшение запросов к этой таблице, когда поля TEXT не были частью запроса, из-за того, что Barracuda не хранит 768 байт большого двоичного объекта на поле, и сократили таблицу до 30 ГБ. Счастливый клиент:)

Одна прощальная идея: вы можете использовать pt-online-schema-change  из Percona Toolkit 2.1 , чтобы изменить таблицу, если вы не можете выдержать блокирующие эффекты традиционного оператора ALTER TABLE.

Я надеюсь, что это поможет вам понять случай использования, когда сжатие таблиц может быть полезным, когда ваша рабочая нагрузка в основном читается. Спасибо за чтение моего первого сообщения в блоге mysqlperformanceblog.com !