У меня есть таблица InnoDB на 700 ГБ, в которую я больше не записываю данные (только чтение). Я хотел бы удалить старые данные, которые он хранит, и освободить это дисковое пространство (так как у меня заканчивается). Часть удаления довольно проста, потому что у меня есть первичный индекс auto-inc, поэтому я могу просто перебирать его по частям и удалять строки, но это не вернет мне пространство. Я предполагаю, что OPTIMIZE TABLE
будет, но это может занять вечность на столе 700 ГБ, так есть ли другой вариант, который я пропускаю?
Редактировать RolandoMySQLDBA
Предполагая, что ваша таблица mydb.mytable
, пожалуйста, запустите следующий запрос и опубликуйте его здесь, чтобы вы могли определить дисковое пространство, необходимое для усадки таблицы:
SELECT
FORMAT(dat/POWER(1024,3),2) datsize,
FORMAT(ndx/POWER(1024,3),2) ndxsize,
FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;
Нам также нужно увидеть структуру таблицы, если это разрешено.
Редактировать Ноам
Это результат запроса:
datsize ndxsize tblsize
682,51 47,57 730,08
Это структура таблицы ( SHOW CREATE TABLE
)
`CREATE TABLE `mybigtable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`created_at` datetime NOT NULL,
`tid` bigint(20) NOT NULL,
`text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`ft` tinyint(1) NOT NULL,
`irtsd` bigint(20) NOT NULL,
`irtuid` int(11) NOT NULL,
`rc` int(11) NOT NULL,
`r` tinyint(1) NOT NULL,
`e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `timezone` varchar(5) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`
ALTER TABLE ... ENGINE=InnoDB;
(если у вас есть место для этого). Большинство просто довольны своими очень быстрыми твердотельными накопителями и больше не будут беспокоиться.Ответы:
Это хороший вопрос. У вас есть несколько решений, но ваш стол довольно большой, поэтому никто не останется без боли :)
У вас есть три решения для «сокращения» таблиц InnoDB:
1. Оптимизировать таблицу
Вы можете использовать,
OPTIMIZE TABLE
как вы упомянули, но вы должны заботиться оinnodb_file_per_table
переменной:Позволь мне объяснить:
OPTIMIZE TABLE
Ти таблиц InnoDB, блокирует таблицу, скопировать данные в новую чистую таблицу (то почему результат усаживается), удаление исходной таблицы и переименуйте новую таблицу с оригинальным названием. Вот почему вы должны позаботиться о том, чтобы на вашем диске была доступна двойная объемная таблица (во время работы вам потребуется 2x700 ГБ).Когда вы находитесь в innodb_file_per_table = ON. Все таблицы имеют соответствующий файл данных. Таким образом,
OPTIMIZE
оператор создаст новый файл данных (~ 700 ГБ), когда операция будет завершена, MySQL отбросит исходный и переименует новый (поэтому в конце 700 ГБ - возможно, меньше, потому что он будет сжат) - данных сгенерированный во время операции будет выпущен)Когда вы находитесь в innodb_file_per_table = OFF. Все данные отправляются в один файл данных: ibdata . Этот файл имеет печальную особенность, его нельзя сжать. Таким образом, во время
OPTIMIZE
процесса будет создана ваша новая таблица (около 700 ГБ), но даже после операции удаления и переименования (и в концеOPTIMIZE
фазы) ваши ибданные не будут освобождать ~ 700 ГБ, поэтому вы хотели освободить некоторые данные, но у вас есть 700 ГБ больше, круто не так ли?2. ALTER TABLE
Вы также можете использовать
ALTER TABLE
оператор, которыйALTER TABLE
будет работать так же, какOPTIMIZE TABLE
. Вы можете просто использовать:3. ALTER TABLE (ОНЛАЙН)
Проблема
OPTIMIZE
иALTER TABLE
что он блокирует таблицу во время работы. Вы можете использовать инструмент Percona: pt-online-schema-change (из Percona Toolkit: ссылка ). pt-online-schema ... создаст механизм с триггерами и временной таблицей, который позволит исходной таблице быть доступной для чтения и записи во время операции. Я использую этот инструмент в производстве для большого,ALTER
это довольно круто.Обратите внимание, что вы должны были
FOREIGN KEY
сослаться на свою таблицу, FK и триггеры рискуют создать беспорядок. Чтобы проверить это prereqs, запрос:Вот как я использую pt-online-schema-change:
Обратите внимание, что мое примечание к innodb_file_per_table верно и для этого решения.
4. mysqldump
Последнее решение - воссоздать все базы данных из дампа. Ужасно долго, но ужасно эффективно. Обратите внимание, что это единственное решение для «сжатия» файла ibdata.
Максимум.
источник
Если вам не хватает размера диска, я бы посоветовал вам сделать то же самое, что Макс предложил с pt-online-schema-change (ONLINE). Я был в той же ситуации с гораздо меньшей таблицей (200 ГБ) и решил сделать сжатие одновременно. Что-то вроде этого должно работать:
Это будет работать, только если вы находитесь в формате файла барракуды и в формате КОМПАКТ таблицы. Также у вас должна быть включена innodb_file_per_table. Это может изумить размер вашей таблицы, особенно если текста много и вы используете меньший KEY_BLOCK_SIZE, например 8K или даже 4K (по умолчанию 16K). Вы также можете проверить, сколько места вы можете получить от нескольких тестов по этой проблеме в других блогах, но документация MySQL рекламирует от 25% до 50% (для меня это было почти 90%).
Обратите внимание, что это также может повлиять на производительность при выполнении SELECT (из документации MySQL):
MySQL также должен распаковывать данные, когда их нет в пуле буферов. Так что будьте осторожны.
Это действительно сработало в моем случае. У меня был длинный текст. 200ГБ стало 26ГБ. Спектакли не были изменены.
Для получения более подробной информации проверьте эти ссылки:
https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html
https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html
источник