Удаление и восстановление пространства из таблицы InnoDB

14

У меня есть таблица 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`
Ноам
источник
У вас есть другой том диска, чтобы ловить только данные ???
RolandoMySQLDBA
@RolandoMySQLDBA У меня есть внешний жесткий диск, который я могу смонтировать. Это считается?
Noam
@RolandoMySQLDBA, но, конечно, хотелось бы, чтобы опция удаляла некоторое пространство без необходимости иметь еще 700 ГБ
Noam
@RolandoMySQLDBA вызывает ли дополнительный размер диска какие-либо проблемы с производительностью?
Арис
@ Может быть, это зависит от диска и времени его поиска. В наши дни большинство дисков работают лучше, но что хорошего в том, чтобы тратить циклы (даже если они идут очень быстро), если в вашей таблице есть большие разреженные карманы дискового пространства ??? Это особенно верно для InnoDB, который обычно фиксируется в 16K-блоках. При внутренней фрагментации блоков по 16 КБ вы можете захотеть дефрагментировать таблицу с помощью ALTER TABLE ... ENGINE=InnoDB;(если у вас есть место для этого). Большинство просто довольны своими очень быстрыми твердотельными накопителями и больше не будут беспокоиться.
RolandoMySQLDBA

Ответы:

21

Это хороший вопрос. У вас есть несколько решений, но ваш стол довольно большой, поэтому никто не останется без боли :)

У вас есть три решения для «сокращения» таблиц InnoDB:

1. Оптимизировать таблицу

Вы можете использовать, OPTIMIZE TABLEкак вы упомянули, но вы должны заботиться о innodb_file_per_tableпеременной:

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

Позволь мне объяснить:

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. Вы можете просто использовать:

ALTER TABLE myTable EGINE=InnoDB;

3. ALTER TABLE (ОНЛАЙН)

Проблема OPTIMIZEи ALTER TABLEчто он блокирует таблицу во время работы. Вы можете использовать инструмент Percona: pt-online-schema-change (из Percona Toolkit: ссылка ). pt-online-schema ... создаст механизм с триггерами и временной таблицей, который позволит исходной таблице быть доступной для чтения и записи во время операции. Я использую этот инструмент в производстве для большого, ALTERэто довольно круто.

Обратите внимание, что вы должны были FOREIGN KEYсослаться на свою таблицу, FK и триггеры рискуют создать беспорядок. Чтобы проверить это prereqs, запрос:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

Вот как я использую pt-online-schema-change:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

Обратите внимание, что мое примечание к innodb_file_per_table верно и для этого решения.

4. mysqldump

Последнее решение - воссоздать все базы данных из дампа. Ужасно долго, но ужасно эффективно. Обратите внимание, что это единственное решение для «сжатия» файла ibdata.

Максимум.

Максим Фуйе
источник
Кроме того, в онлайн-настройке percona tool мне потребуется 700 ГБ свободного дискового пространства?
Noam
Да, pt-online просто использует некоторый механизм для выполнения ALTER онлайн, но в любом случае он создает ALTER.
Максим Фуйе
@MaximeFouilleul ли дополнительный размер диска вызывает проблемы с производительностью?
Арис
1

Если вам не хватает размера диска, я бы посоветовал вам сделать то же самое, что Макс предложил с pt-online-schema-change (ONLINE). Я был в той же ситуации с гораздо меньшей таблицей (200 ГБ) и решил сделать сжатие одновременно. Что-то вроде этого должно работать:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

Это будет работать, только если вы находитесь в формате файла барракуды и в формате КОМПАКТ таблицы. Также у вас должна быть включена 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

Эмерик Охотник
источник