Мне нужно хранить очень большой объем текста в базе данных 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.
ОБНОВИТЬ
Мое приложение – большой литературный сайт, на котором пользователи могут добавлять свои тексты. Вот таблица, которую я имею:
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. У меня есть все основания полагать, что цифры диаграмм увеличиваются. Я не хотел бы хранить тексты в файлах, потому что вокруг довольно много логики, и на моем сайте довольно много хитов.
Собираетесь ли вы индексировать эти тексты. Насколько велика читаемая нагрузка на эти тексты? Вставить нагрузку?
Вы можете использовать сжатие данных InnoDB – прозрачным и современным способом. Дополнительную информацию см. В документах .
Если у вас действительно огромные тексты (скажем, каждый текст выше 10 МБ), то хорошая идея – не хранить их в Mysql. Храните сжатые gzip-тексты в файловой системе и только указатели и мета в mysql. Вы можете легко расширить свое хранилище в будущем и перенести его, например, в DFS.
Обновление: еще один плюс хранения текстов вне 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 .
Если вы сжимаете (например, gzip), не используйте поля TEXT любого типа. Они не являются бинарными. Данные, поступающие в / выходящие из текстовых полей, подвержены трансляции набора символов, что, вероятно (хотя и не обязательно), приводит к искажению сжатых данных и дает вам поврежденный результат при извлечении / распаковке текста.
Вместо этого используйте BLOB-поля, которые являются двоично-прозрачными и не переводят данные.
Возможно, было бы лучше определить текстовое поле как 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']);
Вы также можете использовать параметр COMPRESS для включения сжатия пакетов. Прочтите информацию об этом параметре:
Для PHP я нашел это – MYSQLI_CLIENT_COMPRESS для функции mysqli_real_connect .
Нет никаких преимуществ при сжатии больших текстов в базу данных.
Вот проблемы, с которыми вы можете столкнуться в долгосрочной перспективе:
Я думаю, что хранить эти большие тексты в файл на диске будет проще:
Вы можете использовать функции php gzdeflate и gzinflate для текста.