Подтвердить что ты не робот

Есть ли способ дросселировать индексирование таблиц Mysql, так что общая производительность не влияет?

Мне нужно загрузить большой набор данных в производственную базу данных.

15 файлов должны быть загружены и вставлены в таблицу. Каждый из них составляет 500 МБ.

У меня есть два столбца ID, которые нужно индексировать. Если я загружу файлы с индексами на место, загрузка занимает около 3 часов. Если я отбрасываю индексы, загружаю данные локально, а затем снова добавляю индексы, вся операция занимает около 30 минут.

Проблема заключается в том, что реагирование на базы данных имеет большой успех при индексировании только что импортированных данных. Есть ли способ сделать прогон индексации "низким приоритетом", чтобы другие запросы по-прежнему получали скорость на 95-100% и индексирующий тип chugs в фоновом режиме?

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

Добавление щели к этому, поскольку я все еще хочу видеть, есть ли способ получить хорошую производительность при индексировании в определенном поле.

4b9b3361

Ответ 1

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

Я написал класс с именем CautiousIndexer.

  • Сначала я сохранил инструкцию create table для воссоздания структуры таблицы без индексов. Я сохранил массив считываемых подчиненных баз данных, зацикленных через них, переименовав таблицу с необработанными данными в prevent_indexing_($name).
  • Затем я запустил оператор create table только для ведомых. Это эффективно переместило данные из способа индексирования операторов, которые будут выполняться на главном компьютере.
  • Затем я запустил индексный запрос против мастера. Чтение ведомых не влияет на производительность, пока мастер индексировался, потому что вновь созданные таблицы были пустыми.
  • Когда мастер закончил индексирование, я взял 1 из рабов из ротации производства, сбросил пустую таблицу, переместил всю таблицу на место, а затем проиндексировал таблицу на рабочем ведомом.
  • Когда это закончилось, я вернул его в производство и повторил процедуру индексации ведомого на остальных ведомых.
  • Когда все ведомые индексы были проиндексированы, я помещаю таблицу в производство.

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

Ответ 2

Это не точное решение, которое вы ищете, но вы можете настроить второй экземпляр mysqld в качестве подчиненного устройства в этом одиночном поле и перенаправлять SELECT запросы к нему по мере необходимости. Существует MySQL Proxy, который может помочь вам выполнить это без перезаписывания клиентских приложений.

Вы также можете собрать некоторые идеи из FriendFeed использования MySQL. Они хранят фактические индексы в других таблицах и используют их для поиска. Если вы храните копию данных в другой таблице даже на другом сервере и запускаете там индексы, вы сможете получить доступ к основным данным ASAP на полной скорости и позже получить более быстрые запросы с использованием другого сервера.

Это нравится, если вы добавляете индексы в подчиненное устройство для запросов типа поиска и запускаете только первичные поисковые запросы на главном сервере.

Ответ 3

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

for host in $hosts
do
    mysql -h $host -e "STOP SLAVE;\
      SET sql_log_bin=0;\
      FLUSH TABLE t;\
      ALTER TABLE t ADD INDEX a (b,c);\
      SET sql_log_bin=1;\
      START SLAVE;"
done

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

Ответ 4

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

Ответ 5

Вы можете отключить любые неуникальные индексы при вставке и снова включить их после завершения. Взгляните на отключить клавиши/включить ключи. Но он работает только для неидеальных индексов.

Вы также можете ускорить вставку, если вы используете многопозиционные вставки (вставляете в таблицы (...) значения (...), (...), (...)...

Кстати, load data infile кажется самым быстрым способом вставить много данных в mysql.

Ответ 6

Вы пытались поднять свои параметры индекса для импорта? Это может значительно увеличить производительность импорта. sort_buffer_size для любого типа таблицы, myisam_sort_buffer_size - для таблиц MyISAM. innodb_buffer_pool_size - это своего рода кеш-ключ для Innodb. Удалите их для импорта в зависимости от типа таблицы. То, что вы пытаетесь сделать, это избежать сортировки файлов при создании индекса.

Вы можете получить время импорта/индекса до 10-15 минут или меньше. Он не дросселирует, но значительно сократит период воздействия.

Или, если вы используете таблицы MyISAM, возможно, таблица MERGE является опцией? Создайте новую таблицу, выполните импорт, а затем добавьте новую таблицу в таблицу MERGE. Во время импорта влияние на базу данных не будет. Помимо сервера, выполняющего задачу.