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

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

Необходимо загрузить по 15 файлов и вставить их в таблицу. Размер каждого составляет около 500 МБ.

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

Проблема в том, что отзывчивость базы данных сильно страдает при индексировании только что импортированных данных. Есть ли способ заставить индексирование работать с «низким приоритетом», чтобы другие запросы по-прежнему получали скорость 95-100%, а индексирование выполнялось в фоновом режиме?

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

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


person Zak    schedule 10.05.2011    source источник
comment
Запустите SHOW CREATE TABLE tblname\G для загружаемой таблицы. Нам нужно посмотреть, какой системой хранения является таблица. Пожалуйста, покажите нам файл /etc/my.cnf.   -  person RolandoMySQLDBA    schedule 20.06.2011
comment
В настоящее время я использую myisam, но я также пробовал innodb. Я открыт для использования либо. Опять же, большая проблема заключается в попытке ограничить индекс, а не в попытке повысить производительность.   -  person Zak    schedule 21.06.2011
comment
неясно, как часто вы выполняете эту операцию, но вы, кажется, предполагаете, что это разовая операция. Из любопытства, в чем проблема простоя около 30 минут? Разве это не может быть выполнено в периоды низкого использования (ночь/обед)?   -  person T9b    schedule 23.06.2011
comment
Загрузка данных должна происходить не реже одного раза в неделю, а иногда и раз в день. Меня не волнует, если они займут 6 часов, я просто хочу ограничить их, чтобы они не влияли на остальные запросы.   -  person Zak    schedule 23.06.2011


Ответы (6)


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

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

  1. Сначала я сохранил оператор создания таблицы, чтобы воссоздать структуру таблицы без индексов. Я сохранил массив прочитанных подчиненных баз данных, перебрал их, переименовав таблицу с неиндексированными данными в prevent_indexing_($name).
  2. Затем я запустил оператор создания таблицы только на ведомых устройствах. Это эффективно убрало данные с пути операторов индексации, которые могли бы произойти на мастере.
  3. Затем я выполнил индексный запрос к мастеру. Ведомые устройства чтения не влияли на производительность, пока мастер выполнял индексацию, поскольку вновь созданные таблицы были пустыми.
  4. Когда мастер закончил индексирование, я вывел 1 из подчиненных устройств из ротации производства, удалил пустую таблицу, вернул полную таблицу на место, а затем проиндексировал таблицу на снятом с производства подчиненном устройстве.
  5. Когда это закончилось, я вернул его в производство и повторил процедуру индексации ведомых устройств на оставшихся ведомых устройствах.
  6. Когда все ведомые устройства были проиндексированы, я запустил таблицу в производство.

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

person Zak    schedule 18.05.2011
comment
Это решение помогло, но я обнаружил, что этого недостаточно. Некоторым запросам по-прежнему требуется прямой доступ к главной базе данных для транзакций, и они неприемлемо замедляются во время индексации. - person Zak; 21.06.2011

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

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

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

person memnoch_proxy    schedule 20.06.2011
comment
В настоящее время я делаю почти именно это, но этого все еще недостаточно. Индексация данных на мастере приводит к тому, что 0,5% запросов, которым требуются мастер-данные, выполняются слишком медленно. Мне нужен способ ограничить индексацию, чтобы она могла индексироваться, но при этом реагировать на другие таблицы. - person Zak; 21.06.2011
comment
Зак, у тебя есть отличный бизнес-кейс для покупки большего количества оборудования! Другая возможность - сделать индексацию таблицы на ведомом устройстве, скопировать ее на ведущее устройство, а затем переименовать, например, SET sql_log_bin=0; flush table t; rename t to dugout_t, t_atbat to t; SET sql_log_bin=1;. - person memnoch_proxy; 23.06.2011
comment
Я как бы в уловке 22. Я перешел на RDS, чтобы избежать затрат на системного администратора, но платить больше за машино-час. Однако RDS не позволит вам переместить индекс или таблицу на место, потому что у вас нет прямого доступа к файловой системе. Если я увеличу размер своей БД в RDS, я потеряю все средства, сэкономленные на системном администраторе, поскольку многозонные БД, которые я использую, действительно начинают дорожать! - person Zak; 23.06.2011
comment
Это также решается политикой и обменом сообщениями с клиентами. Есть ли у вашего сайта особое соглашение об уровне обслуживания с клиентами? Подумайте о том, чтобы создать уведомление о техническом обслуживании сайта на страницах входа ваших клиентов, предупреждающее их о деградации или отключении службы, а затем сделайте неприятное в дату и время, о которых вы их предупредили. - person memnoch_proxy; 23.06.2011

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

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

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

person sanmai    schedule 20.06.2011
comment
Это было бы хорошо, если бы мне не нужно было также обрабатывать транзакции. Мне нужен мастер, чтобы я мог писать на него. Запись слишком сильно замедляется (в других таблицах) во время индексации. - person Zak; 23.06.2011
comment
Я добавил примечание о том, что на самом деле они сделали в FriendFeed. - person sanmai; 24.06.2011

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

person Asad Rasheed    schedule 18.06.2011

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

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

Кстати, загрузка файла данных кажется самым быстрым способом вставки большого количества данных в mysql.

person Maxim Krizhanovsky    schedule 19.06.2011
comment
Да, я могу загрузить все данные примерно за 5 минут с отключенными ключами.. Но когда я включаю ключи, происходит индексация! Это то, что убивает мою производительность БД. - person Zak; 23.06.2011

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

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

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

person Brent Baisley    schedule 23.06.2011