Обслуживание индексов MySQL

12

Я провел много исследований о том, как поддерживать индексы в MySQL, чтобы предотвратить фрагментацию и каким-то образом оптимизировать выполнение некоторых запросов.

Я знаком с этой формулой, которая вычисляет соотношение между максимальным пространством, доступным для таблицы, и пространством, используемым данными и индексами.

Однако мои основные вопросы до сих пор остаются без ответа. Возможно, это связано с тем, что я знаком с ведением индексов в SQL Server и склонен думать, что в MySQL это должно быть как-то похоже.

В SQL-сервере у вас может быть несколько индексов, и каждый из них может иметь разные уровни фрагментации. Затем вы можете выбрать один и выполнить операцию «REORGANIZE» или «REBUILD» в этом конкретном индексе, не затрагивая остальные.

Насколько я знаю, «фрагментация таблиц» как таковая отсутствует, и SQL Server не предоставляет никаких инструментов для устранения «фрагментации таблиц». Он предоставляет инструменты для проверки фрагментации индекса (понимается как отношение числа страниц, используемых индексом к полноте этой страницы и смежности), а также внутренней и внешней фрагментации.

Все это довольно просто понять, по крайней мере, для меня.

Теперь, когда наступает черед поддерживать индексы в MySQL, существует только концепция «фрагментации таблиц», как упоминалось выше.

Таблица в MySQL может иметь несколько индексов, но когда я проверяю «коэффициент фрагментации» с помощью этой известной формулы, я не вижу фрагментации каждого индекса, а таблицы в целом.

Когда я хочу оптимизировать индексы в MySQL, я не выбираю определенный индекс для работы (как в SQL Server). Вместо этого я делаю операцию «ОПТИМИЗАЦИЯ» во всей таблице, которая предположительно влияет на все индексы.

Когда таблица оптимизирована в 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 КБ; свободные "экстенты" (куски nMB); Строки MVCC, ожидающие сбора; неконечные узлы имеют свою собственную фрагментацию; и т.п.

У Percona и Oracle разные взгляды на то, насколько велик (количество блоков) индекс. Я не нахожу ни одного из них полезным из-за ограниченного определения «бесплатный». Кажется, что блоки (по 16 КБ каждый) выделяются в виде кусков (несколько МБ), тем самым наводя на мысль, что существует разного рода фрагментация. На самом деле, это обычно просто один из этих блоков размером в несколько МБ. И OPTIMIZE TABLEне обязательно окупить любое пространство.

Если SQL Server использует BTrees, то неправда, что «фрагментации нет». Подумайте о том, что происходит на «раскол блока». Или подумайте о накладных расходах на постоянную дефрагментацию. В любом случае вы проигрываете.

Далее отметим, что таблица и индекс являются по существу идентичными структурами:

  • Дерево B +, основанное на некотором индексе
  • «Данные» основаны на ПЕРВИЧНОМ КЛЮЧЕ; каждый вторичный индекс является деревом B + на основе его индекса.
  • Конечный узел «данных» содержит все столбцы таблицы.
  • Конечный узел вторичного индекса содержит столбцы этого вторичного индекса, а также столбцы PRIMARY KEY.

Если у вас есть 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)может быть полезно.)

Вопрос 1: Нет хорошего способа проверить все формы фрагментации ни в данных, ни во вторичных индексах.

Q2, Q3: OPTIMIZE TABLEперестраивает таблицу по CREATEingновой таблице и INSERTingвсем строкам, затем RENAMEingи DROPping. Повторная вставка данных в порядке PK гарантирует, что данные хорошо дефрагментированы. Индексы это другое дело.

Q4: Вы можете DROP и reCREATEкаждый индекс очистить его. Но это очень медленный процесс. В 5.6 есть некоторые ускорения, но я не знаю, помогают ли они в дефрагментации.

Так же можно ALTER TABLE ... DISABLE KEYS, потом ENABLEим. Это может привести к более эффективной перестройке всех вторичных индексов одновременно.

Рик Джеймс
источник
Рик, я имел в виду поля «105», а не файлы
Николас
1

Как проверить фрагментацию определенного индекса в MySQL, а не таблицы в целом

Проходить.

Исправляет ли OPTIMIZE TABLE внутреннюю / внешнюю фрагментацию индекса, как в SQL Server?

Он полностью перестраивает таблицу и ее индексы.

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

Это тот же вопрос с тем же ответом.

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

Нереально думать, что вы могли бы уменьшить пространство, не восстанавливая дерево. Они идут вместе.

user207421
источник
Ответить # 1: Хотя это не очень точно, но SHOW TABLE STATUS LIKE 'mytable'даст подсказку в data freeстолбце. dev.mysql.com/doc/refman/5.6/en/show-table-status.html
Джехад Кериаки
Я знаю, но это все еще не хватает места определенного индекса
Николас