Як видалити фрагментацію з таблиць InnoDB?


13

У мене База даних має кількість таблиць.

Я хочу видалити деякі записи з таблиць, мовляв, кількість записів становить більше 20 К або 50 К.

Усі таблиці є InnoDB. І file_per_tableце геть .

Коли я видалю записи з ряду таблиць, у таблицях буде фрагментація.

Чи є спосіб видалити фрагментацію?

Оновлення 17 квітня

mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME      | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City            | world_innodb |   5242880 |
| City_Copy       | world_innodb |   5242880 |
| Country         | world_innodb |   5242880 |
| CountryLanguage | world_innodb |   5242880 |
| a               | world_innodb |   5242880 |
| t1              | world_innodb |   5242880 |
| t2              | world_innodb |   5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)

Тож тепер моє запитання полягає в тому, як я вирішу, що мої таблиці фрагментовані чи ні.



1
І стаття InnoDB: доглядайте за фрагментацією з сайту блогу Percona.
ypercubeᵀᴹ

Відповіді:


14

Я вирішив це в StackOverflow ще в жовтні 2010 року .

Майте на увазі найзайнятіший файл в інфраструктурі InnoDB: / var / lib / mysql / ibdata1

Цей файл зазвичай містить чотири типи інформації

  • Дані таблиці
  • Табличні покажчики
  • Дані MVCC (мультивалюючий контроль за сумісністю)
  • Метадані таблиці (Список ідентифікаторів простору таблиць)

Запуск OPTIMIZE TABLEпроти таблиці InnoDB, що зберігається в ibdata1, робить дві речі:

  • Робить дані таблиці та індекси суміжними всередині ibdata1, тим самим швидше отримуючи доступ
  • Це змушує ibdata1 рости, оскільки суміжні сторінки даних та покажчики додаються до ibdata1

Хоча ви можете відокремлювати дані таблиці та індекси таблиць від ibdata1 та керувати ними самостійно, використовуючи innodb_file_per_table , велика розбіжна ціла дискова область в ibdata1 просто не вийде з ладу і не може бути відновлена. Ви повинні зробити більше.

Щоб скоротити ibdata1 раз і назавжди, ви повинні зробити наступне:

1) MySQLDзавантажте всі бази даних у текстовий файл SQL (назвіть це /root/SQLData.sql)

2) Відкинути всі бази даних (крім схеми mysql)

3) Вимкнення mysql

4) Додайте наступні рядки до /etc/my.cnf

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

Сторінка: Незалежно від вашого набору для innodb_buffer_pool_size, переконайтесь, що innodb_log_file_size становить 25% від innodb_buffer_pool_size.

5) Видаліть ibdata1, ib_logfile0 та ib_logfile1

На цьому етапі має бути лише схема mysql в / var / lib / mysql

6) Перезапустіть mysql

Це відтворить ibdata1 у 10 або 18 МБ (залежно від версії MySQL), ib_logfile0 та ib_logfile1 на 1G кожен

7) Перезавантажте /root/SQLData.sql в mysql

ibdata1 зростатиме, але містить лише метадані таблиці. Насправді він росте дуже повільно з роками. Єдиний спосіб швидкого зростання ibdata1 - це якщо у вас є одне або більше з наступного:

  • Багато DDL ( CREATE TABLE, DROP TABLE, ALTER TABLE)
  • Дуже багато угод
  • Багато змін, які потрібно здійснити за кожну транзакцію

Кожна таблиця InnoDB буде існувати поза ibdata1

Припустимо, у вас є таблиця InnoDB під назвою mydb.mytable. Якщо зайти в / var / lib / mysql / mydb, ви побачите два файли, що представляють таблицю

  • mytable.frm (Заголовок двигуна зберігання)
  • mytable.ibd (Домашні дані таблиці та індекси таблиць для mydb.mytable)

ibdata1 більше ніколи не буде містити дані InnoDB та індекси.

За допомогою параметра innodb_file_per_table в /etc/my.cnf ви можете запустити OPTIMIZE TABLE mydb.mytable;і файл /var/lib/mysql/mydb/mytable.ibd фактично скоротиться.

Я робив це багато разів у своїй кар'єрі як MySQL DBA

Насправді, коли я це зробив, я згорнув файл ibdata1 об'ємом 50 ГБ на 500 Мб.

Спробувати. Якщо у вас є додаткові запитання з цього приводу, напишіть мені. Довірся мені. Це спрацює в короткостроковій перспективі і в довгостроковій перспективі !!!

ОНОВЛЕННЯ 2012-04-19 09:23 EDT

Після виконання вищезазначених кроків, як можна визначити, які таблиці потрібно дефрагментацію? Це можна дізнатися, але у вас буде сценарій.

Ось приклад: припустимо, у вас є таблиця mydb.mytable. Якщо ввімкнено innodb_file_per_table, у вас є файл /var/lib/mysql/mydb/mytable.ibd

Вам доведеться отримати два числа

ФАЛІЗАЦІЯ З ОС: Ви можете встановити розмір файлів в ОС таким чином

ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'

ФАЛІЗАЦІЯ З ІНФОРМАЦІЇ_ШЕМИ: Ви можете встановити розмір файлів з інформаційних таблиць, таких як:

SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';

Просто відніміть значення INFORMATION_SCHEMA від значення ОС і розділіть різницю на значення INFORMATION_SCHEMA.

Звідти ви вирішите, який відсоток вважаєте за потрібне дефрагментувати цю таблицю. Звичайно, ви дефрагментуєте його за допомогою однієї з наступних команд:

OPTIMIZE TABLE mydb.mytable;

або

ALTER TABLE mydb.mytable ENGINE=InnoDB;

я не думаю, що / var / lib / mysql / ibdata1 дуже зайнятий, якщо використовуєш рекомендований варіант innodb_file_per_table = 1
CrackerJack9

1
@ CrackerJack9 ibdata1 неймовірно надзвичайний через те, що потрапляє в нього: 1) Інформація про буфер подвійного запису, 2) Вставка буфера для вторинних індексів, 3) Словник даних, 4) Відхилення сегментів, 5) Скасування простору таблиць. Будь ласка, перейдіть на сторінку scribd.com/doc/31337494/XtraDB-InnoDB-internals-in-drawing для зображувального зображення цих речей. Навіть із видаленням даних та індексних сторінок для таблиць InnoDB, ibdata1 все ще може значно зростати у високому транзакційному середовищі.
RolandoMySQLDBA

1
@ CrackerJack9 У мене є додаткова публікація, в якій обговорюються додаткові дії навколо ibdata1: dba.stackexchange.com/a/23367/877
RolandoMySQLDBA

Я не розумів, що його все ще використовують настільки сильно. Дуже вдячний!
CrackerJack9

@RolandoMySQLDBA Чи можете ви вискочити на Купі, коли встигнете?
ypercubeᵀᴹ

5

Якщо ви часто видаляєте рядки (або оновлюєте рядки з типами даних змінної довжини), у ваших файлах даних може бути багато марного місця, подібно до фрагментації файлової системи.

Якщо ви не використовуєте цю innodb_file_per_tableопцію, єдине, що ви можете зробити з цим - це експортувати та імпортувати базу даних, що вимагає часу та диска.

Але якщо ви використовуєте innodb_file_per_table, ви можете визначити та відновити цей простір!

До 5.1.21 лічильник вільного простору доступний у стовпці_коментар таблиці_інформації_schema.tables. Ось декілька SQL для ідентифікації таблиць із щонайменше 100М (фактично 97,65М) вільного простору:

SELECT table_schema, table_name, table_comment FROM
information_schema.tables WHERE ENGINE LIKE 'InnoDB' AND table_comment RLIKE 'InnoDB free: ([0-9] {6,}). *';

Починаючи з 5.1.21, це було переміщено до стовпця "Безкоштовно" (набагато підходяще місце):

SELECT table_schema, table_name, data_free / 1024/1024 AS data_free_MB FROM information_schema.tables WHERE ENGINE LIKE 'InnoDB' AND data_free> 100 * 1024 * 1024;

Ви можете повернути втрачений простір, відновивши стіл. Найкращий спосіб зробити це за допомогою "таблиці змін", фактично нічого не змінюючи:

ALTER TABLE `TableName` ENGINE=InnoDB;

Це те, що MySQL робить поза кадром, якщо ви запускаєте "оптимізувати таблицю" в таблиці InnoDB. Це призведе до блокування читання, але не до повного блокування таблиці. Скільки часу це триває, повністю залежить від кількості даних у таблиці (але не від розміру файлу даних). Якщо у вас є таблиця з великим обсягом видалень або оновлень, ви можете запустити цей місяць або навіть щотижня.


Ще одне, що я не в змозі зрозуміти, що означає значення data_free> 100 * 1024 * 1024 ..? І коли я побачив результат, я не можу визначити, що таблиця є фрагментованою чи ні .. Чи є спосіб, щоб я можна сказати, таблиця роздроблена чи не фрагментована.?
Абдул Манаф

подивіться на мою частину оновлення.
Абдул Манаф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.