Сжатие текста перед его сохранением в базе данных

Мне нужно сохранить очень большой объем текста в базе данных mysql. Это будут миллионы записей с полем типа LONGTEXT, а размер базы данных будет огромным.

Итак, я хочу спросить, есть ли безопасный способ сжимать текст перед сохранением его в поле TEXT для экономии места, с возможностью его извлечения при необходимости?

Что-то вроде:

$archived_text = compress_text($huge_text);
// saving $archived_text to database here
// ...

// ...
// getting compressed text from database
$archived_text = get_text_from_db();
$huge_text = uncompress_text($archived_text);

Есть ли способ сделать это с помощью php или mysql? Все тексты кодируются utf-8.

UPDATE

Мое приложение - большой литературный сайт, где пользователи могут добавлять свои тексты. Вот таблица, которая у меня есть:

CREATE TABLE `book_parts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `book_id` int(11) NOT NULL,
  `title` varchar(200) DEFAULT NULL,
  `content` longtext,
  `order_num` int(11) DEFAULT NULL,
  `views` int(10) unsigned DEFAULT '0',
  `add_date` datetime DEFAULT NULL,
  `is_public` tinyint(3) unsigned NOT NULL DEFAULT '1',
  `published_as_draft` tinyint(3) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `key_order_num` (`order_num`),
  KEY `add_date` (`add_date`),
  KEY `key_book_id` (`book_id`,`is_public`,`order_num`),
  CONSTRAINT FOREIGN KEY (`book_id`) REFERENCES `books` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

В настоящее время он имеет около 800 тыс. записей и весит 4 ГБ, 99% запросов - SELECT. У меня есть все основания полагать, что цифры диаграмм увеличиваются. Я не хотел бы хранить тексты в файлах, потому что вокруг довольно много логики, и на моем сайте довольно много хитов.

Ответ 1

Собираетесь ли вы индексировать эти тексты. Насколько велика читаемая нагрузка на эти тексты? Вставить нагрузку?

Вы можете использовать сжатие данных InnoDB - прозрачным и современным способом. Подробнее см. docs.

Если у вас действительно огромные тексты (скажем, каждый текст выше 10 МБ), хорошая идея - не хранить их в Mysql. Храните сжатые gzip-тексты в файловой системе и только указатели и мета в mysql. Вы можете легко расширить свое хранилище в будущем и перенести его, например. ДФС.

Обновление: еще один плюс хранения текстов вне Mysql: DB остается маленьким и быстрым. Минус: высокая вероятность несогласованности данных.

Обновить 2:, если у вас много ресурсов для программирования, пожалуйста, посмотрите на проекты вроде этого: http://code.google.com/p/mysql-filesystem-engine/.

Окончательное обновление: согласно вашей информации, вы можете просто использовать сжатие InnoDB - это то же самое, что и ZIP. Вы можете начать с этих параметров:

CREATE TABLE book_parts
 (...) 
 ENGINE=InnoDB
 ROW_FORMAT=COMPRESSED 
 KEY_BLOCK_SIZE=8;

Позже вам нужно будет сыграть с KEY_BLOCK_SIZE. См. SHOW STATUS LIKE 'COMPRESS_OPS_OK' и SHOW STATUS LIKE 'COMPRESS_OPS'. Отношение этих двух параметров должно быть близко к 1.0: Docs.

Ответ 2

Если вы сжимаете (например, gzip), не используйте поля TEXT любого типа. Они не являются бинарными. Данные, поступающие в/выходящие из текстовых полей, подвержены трансляции набора символов, что, вероятно, (хотя и не обязательно) приводит к искажению сжатых данных и дает поврежденный результат при извлечении/распаковывании текста.

Вместо этого используйте BLOB-поля, которые являются двоично-прозрачными и не переводят данные.

Ответ 3

Лучше определить текстовое поле как blob и сжать данные в PHP, чтобы сэкономить затраты в общении.

CREATE TABLE book_parts (
    ......
    content blob default NULL,
    ......
)

В PHP используйте gzcompress и gzuncompress.

$content = '......';
$query = sprintf("replace into book_parts(content) values('%s') ",
        mysql_escape_string(gzcompress($content)) );
mysql_query($query); 


$query = "select * from book_parts where id = 111 ";
$result = mysql_query($query);
if ($result && $row = mysql_fetch_assoc($result))
    $content = gzuncompress($row['content']);

Ответ 4

Нет никаких преимуществ при сжатии больших тексты в базу данных.

Вот проблемы, с которыми вам придется столкнуться в долгосрочной перспективе:

  • Если сервер сбой данных может быть сложно восстановить.
  • Не подходит для поиска.
  • Требуется дополнительное время для передачи данных между сервером mysql и браузером.
  • Требуется много времени для резервного копирования (без использования репликации).

Я думаю, что сохранить эти большие тексты в файл на диске будет проще:

  • Распределенное резервное копирование (rsync).
  • PHP для загрузки файлов.

Ответ 6

Вы можете использовать функции php gzdeflate и gzinflate для текста.