Сжатие текста перед его сохранением в базе данных
Мне нужно сохранить очень большой объем текста в базе данных 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 для загрузки файлов.
Ответ 5
Вы также можете использовать параметр COMPRESS для включения сжатия пакетов.
Прочтите информацию об этой опции:
Для PHP я нашел это - MYSQLI_CLIENT_COMPRESS для функции mysqli_real_connect.
Ответ 6
Вы можете использовать функции php gzdeflate и gzinflate для текста.