Добавление индекса в большие таблицы MySQL

13

У меня есть стол

| base_schedule_line_items | CREATE TABLE base_schedule_line_items(
idint (10) без знака NOT NULL AUTO_INCREMENT,
installmentint (10) без знака NOT NULL,
on_dateдата NOT NULL,
actual_dateдата DEFAULT NULL,
payment_typeint (11) NOT NULL,
scheduled_principal_outstandingдесятичный (65,0) NOT NULL,
scheduled_principal_dueдесятичный (65,0) NOT NULL,
scheduled_interest_outstandingдесятичный (65,0) NOT NULL,
scheduled_interest_dueдесятичный (65,0) NOT NULL,
currencyint (11) NOT NULL,
updated_atdatetime NOT NULL DEFAULT '2013-01-06 14:29:16',
created_atdatetime NOT NULL DEFAULT ' 2013-01-06 14:29:16 ',
loan_base_schedule_idint (10) без знака NOT NULL,
lending_idint (10) без знака NOT NULL,
rescheduletinyint (1) ПО УМОЛЧАНИЮ' 0 ',
PRIMARY KEY ( id),
KEY index_base_schedule_line_items_loan_base_schedule ( loan_base_schedule_id), KEY index_bslt_spd( scheduled_principal_due),
КЛЮЧ index_bslt_lending(lending_id),
KEY index_bslt_actualdate( actual_date),
KEY index_bslt_spsila ( loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
KEY index_bslt_ondate( on_date),
KEY index_bslt_oa( on_date, actual_date),
KEY index_bslt_ol( on_date, loan_base_schedule_id),
KEY index_bslt_oli( on_date, lending_id)
) ENGINE = InnoDB AUTO_INCREMENT = 30410126 DEFAULT CHARSET = utf8 |

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

изменить таблицу base_schedule_line_items добавить индекс index_bslt_sla (schedule_principal_due, actual_date, lending_id);
изменить таблицу base_schedule_line_items добавить индекс index_bslt_ssla (schedule_principal_due, schedule_interest_due, lending_id, actual_date);

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

ВЫБЕРИТЕ имя_таблицы AS "Таблицы", круглое (((data_length + index_length) / 1024/1024), 2) "Размер в мегабайтах" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

Результат получился как

base_schedule_line_items | 20111,00

Я использовал это только для вычисления длины данных и опущенной длины индекса

ВЫБЕРИТЕ имя_таблицы AS "Tables", round (((data_length) / 1024/1024), 2) "Размер в мегабайтах" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

и результат был

base_schedule_line_items | 9497,00

Индексы

КЛЮЧ index_bslt_actualdate (actual_date),
КЛЮЧ index_bslt_spsila (loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
КЛЮЧ index_bslt_ondate (on_date),
КЛЮЧ index_bslt_oa (on_date, actual_date),
КЛЮЧ index_bslt_ol (on_date, loan_base_schedule_id),
КЛЮЧ index_bslt_oli (on_date, lending_id)

были добавлены мной, но я не уверен, или для какой цели были добавлены другие индексы. Это довольно большое приложение. Теперь мне нужно добавить эти два индекса, упомянутые выше, поскольку они помогают мне извлечь отчет с помощью оператора select, и мне очень трудно добавить их. Любая помощь будет принята с благодарностью

user2294477
источник

Ответы:

16

Действия по изменению больших таблиц выполняются поэтапно:

  1. Создайте новую таблицу с необходимыми полями и индексами, скажем, в тестовой БД (просто структура)
  2. Сбросить данные из существующей таблицы и загрузить их во вновь созданную таблицу в тестовой БД
  3. Теперь объявите свое время простоя :)
  4. Поменяйте местами таблицы, переименовав - RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;это атомарная операция, занимающая доли секунды.
  5. Загрузите дополнительные записи во вновь созданную таблицу (записи, которые появились после выгрузки и последующей загрузки). Этот шаг может быть выполнен до шага 3 также один раз, чтобы сократить время простоя.
  6. И ваша система вернулась

Несколько заметок:

  1. Вам не нужно напрямую нажимать на информационную схему, попробуйте использовать SHOW TABLE STATUS from db like 'table_name'
  2. Скорость изменения таблицы более или менее связана со скоростью ввода / вывода. В прошлый раз, когда мы запускали таблицу прямого изменения (без вышеуказанных шагов), у нас было 40 ГБ + размер таблицы, это занимало около 4 часов. Если ваши 20 ГБ данные занимают годы, вы работаете на какой-то устаревшей машине.
  3. Кроме того, удаление нежелательных индексов, как index_bslt_ondate, index_base_schedule_line_items_loan_base_scheduleи некоторых других индексов, имеет самый левый столбец в качестве индексированного столбца.

Пожалуйста, дайте мне знать, если вам нужны какие-либо разъяснения по любому из этих шагов.

Изменить: простой скрипт на Python для автоматизации процесса https://github.com/georgecj11/hotswap_mysql_table.git

georgecj11
источник
10

Вы можете использовать такой инструмент, как pt-online-schema-change, чтобы добавить индекс, не блокируя ваше приложение. Основная логика заключается в следующем:

  • создать пустую копию таблицы с новым индексом
  • добавить триггеры к существующей таблице, чтобы любые изменения, попавшие в таблицу, были применены к копии таблицы *
  • начать копирование строк из старой таблицы в новую
  • когда копирование завершено, поменяйте местами таблицы
  • брось старый стол

* Инструмент не работает, если на столе имеются триггеры

Режим обмена и переключения может быть отрегулирован на основе параметров, переданных инструменту.

Кроме того, существуют проблемы с внешними ключами, поэтому обязательно прочитайте документацию инструмента, чтобы полностью понять, что он делает.

И, конечно же, разумно убедиться, что у вас есть резервная копия таблицы, которую можно восстановить в случае необходимости.

Дерек Дауни
источник