Обслуговування індексів MySQL


12

Я зробив багато досліджень про те, як підтримувати індекси в MySQL, щоб запобігти фрагментації та якось оптимізувати виконання деяких запитів.

Мені знайома та формула, яка обчислює відношення між максимальним простором, доступним для таблиці VS, простором, використовуваним даними та індексами.

Однак мої основні питання досі не відповіді. Можливо, це пов'язано з тим, що я знайомий із підтримкою індексу в SQL Server, і я схильний вважати, що в MySQL це має бути якось схоже.

На сервері SQL ви можете мати кілька індексів, і кожен з них може мати різний рівень фрагментації. Тоді ви можете забрати один і виконати операцію «REORGANIZE» або «REBUILD» у цьому конкретному індексі, не впливаючи на решту.

Наскільки мені відомо, немає "фрагментації таблиці" як такої, і SQL Server не надає жодного інструменту для виправлення "фрагментації таблиці". Він надає інструменти для перевірки фрагментації індексу (розуміється як співвідношення між кількістю сторінок, використовуваних індексом VS, повнотою цієї сторінки та суміжністю), а також внутрішньою та зовнішньою фрагментацією.

Все це досить просто зрозуміти, принаймні для мене.

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

Таблиця в MySQL може мати декілька індексів, але коли я перевіряю 'коефіцієнт фрагментації' за допомогою цієї відомої формули, я не бачу фрагментації кожного індексу, а таблиці в цілому.

Коли я хочу оптимізувати індекси в MySQL, я не вибираю конкретний індекс для роботи (як у SQL Server). Натомість я роблю операцію 'OPTIMIZE' у всій таблиці, яка, імовірно, впливає на всі індекси.

Коли таблиця оптимізована в MySQL, відношення між простором, використовуваним даними + індексами VS, загальним простором зменшується, що говорить про певну фізичну переорганізацію на жорсткому диску, що перетворюється на зменшення фізичного простору. Однак фрагментація індексу стосується не лише фізичного простору, але і структури дерева, яка з часом змінювалася завдяки вставленням та оновленням.

Нарешті, я отримав таблицю в InnoDB / MySQL. Ця таблиця містить 3 мільйони записів, 105 стовпців і 55 індексів. Це 1,5 ГБ без урахування індексів, що становить 2,1 ГБ.

Ця таблиця потрапляє тисячі разів за день для оновлення, вставки (ми фактично не видаляємо записи).

Ця таблиця створена роками, і я точно знаю, що ніхто не підтримує індекси.

Я очікував, що там знайдуться величезна фрагментація, але коли я виконую обчислення фрагментації, як було призначено

free_space / (data_length + index_length)

виявляється, у мене лише 0,2% фрагментація. ІМХО - це зовсім нереально.

Отже, великі питання:

  1. Як перевірити фрагментацію певного індексу в MySQL, а не таблиці в цілому
  2. Чи дійсно OPTIMIZE TABLE фіксує внутрішню / зовнішню фрагментацію індексу, як у SQL Server?
  3. Коли я оптимізую таблицю в MySQL, чи реально вона відновлює всі індекси в таблиці?
  4. Чи реально думати, що зменшення фізичного простору індексу (без перебудови самого дерева) насправді призводить до кращої продуктивності?

Таблиця оптимізації, безумовно, очищає кластерний індекс в innodb

1
це чудове питання, просто не програмування. Переїдемо туди, куди належить:>

Відповіді:


6

Фрагментація індексу значно завищена. Не хвилюйтеся про це.

Два сусідні, дещо порожні блоки, об'єднуються InnoDB як природна обробка.

Випадкові дії на BTree природно тяжіють до середнього на 69%. Впевнений, це не на 100%, але накладні витрати «фіксувати» не варто.

SHOW TABLE STATUS дає деякі показники, але вони є хибними - "Data_free" включає певний "вільний" простір, але не інший "вільний" простір.

У кожному блоці є невикористаний простір; безкоштовні блоки 16 КБ; безкоштовні "екстенти" (шматочки нМБ); Ряди MVCC, які чекають пожинання; нелистові вузли мають власну фрагментацію; тощо.

У Percona та Oracle по-різному спостерігається, наскільки великий (кількість блоків) індекс. Я не вважаю жоден із них корисним через обмежене визначення поняття "безкоштовно". Здається, що блоки (по 16 КБ кожен) виділяються шматками (кілька МБ), тим самим змушуючи повірити, що існує всіляка фрагментація. Насправді це, як правило, просто більшість одного з цих шматок МБ. І OPTIMIZE TABLEне обов’язково відшкодувати будь-який простір.

Якщо SQL Server використовує BTrees, то брешуть сказати, що "фрагментації немає". Подумайте, що відбувається на "блок-розщепленні". Або подумайте про накладні витрати постійно дефрагментації. У будь-якому випадку ви програєте.

Далі зауважте, що таблиця та індекс - це по суті ідентичні структури:

  • B + Дерево, виходячи з деякого індексу
  • "Дані" базуються на ПЕРВІЙНОМУ КЛЮЧІ; кожен вторинний індекс - це B + Дерево на основі свого індексу.
  • Листовий вузол "даних" містить усі стовпці таблиці.
  • Вузол аркуша вторинного індексу містить стовпці цього вторинного індексу плюс стовпці ПЕРВИЧНОГО КЛЮЧА.

Якщо у вас є innodb_file_per_table = ON, ви можете чітко побачити усадку (якщо вона є) після OPTIMIZE TABLE, переглянувши розмір .ibdфайлу. Адже OFFінформація захована ibdata1, але SHOW TABLE STATUSможе бути досить точною, оскільки весь «вільний» простір належить кожній таблиці. Ну, за винятком попередньо виділених шматочків.

Ви можете помітити, що свіжооптимізована таблиця файлів за столом містить рівно 4M, 5M, 6M або 7M Data_free. Знову ж таки, це попереднє виділення та неможливість детальної інформації.

Я працював з InnoDB більше десяти років; Я працював з тисячами різних таблиць, великих і малих. Я кажу, що справді потрібна лише одна таблиця на тисячу OPTIMIZE TABLE. Використання його на інших столах - марно.

105 стовпців - це багато, але, можливо, не дуже багато.

У вас 55 індексів на одній таблиці? Це погано. Це 55 оновлень на INSERT. Давайте обговоримо це далі. Майте на увазі, що INDEX(a)марно, якщо і у вас є INDEX(a,b). І INDEX(flag)марний через низьку кардинальність. (Але INDEX(flag, foo)може бути корисним.)

Q1: Немає хорошого способу перевірити наявність усіх форм фрагментації ні в даних, ні в вторинних індексах.

Q2, Q3: OPTIMIZE TABLEперебудовує таблицю за CREATEingдопомогою нової таблиці та INSERTingвсіх рядків, потім RENAMEingі DROPping. Повторне введення даних у порядку ПК гарантує, що дані добре дефрагментовані. Індекси - інша справа.

Q4: Ви можете DROP і reCREATEкожен індекс, щоб очистити його. Але це надзвичайно повільний процес. 5.6 має кілька прискорень, але я не знаю, чи допоможуть вони дефрагментації.

Можна також ALTER TABLE ... DISABLE KEYS, тоді ENABLEїх. Це може призвести до більш ефективної перебудови всіх вторинних індексів одночасно.


Рік, я мав на увазі поля "105", а не файли
Ніколас

1

Як перевірити фрагментацію певного індексу в MySQL, а не таблиці в цілому

Перехід.

Чи дійсно OPTIMIZE TABLE фіксує внутрішню / зовнішню фрагментацію індексу, як у SQL Server?

Він повністю відновлює таблицю та її індекси.

Коли я оптимізую таблицю в MySQL, чи реально вона відновлює всі індекси в таблиці?

Це те саме питання з тією ж відповіддю.

Чи реально думати, що зменшення фізичного простору індексу (без перебудови самого дерева) насправді призводить до кращої продуктивності?

Не реально думати, що ви могли б зменшити простір, не будуючи дерево. Вони йдуть разом.


Відповідь №1: Хоча це не дуже точно, але SHOW TABLE STATUS LIKE 'mytable'дасть підказку у data freeколонці. dev.mysql.com/doc/refman/5.6/uk/show-table-status.html
Джехад Керіякі

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