Назад | Перейти на главную страницу

Как улучшить производительность MySQL INSERT и UPDATE?

Этот вопрос, вероятно, можно задать и в StackOverflow, но сначала я попробую здесь ...

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

Таблицы - это InnoDB, и приложение использует транзакции. Есть ли какие-нибудь простые настройки, которые я могу сделать, чтобы ускорить работу?

Я думаю, у нас могут быть проблемы с блокировкой, как я могу узнать?

  1. Убедитесь, что ваше оборудование и ОС правильно настроены и настроены:

    • Источник проблемы (использование ЦП / ввода-вывода / памяти / подкачки). У вас много ВГД? ЦП загружен? Если у вас много IOP для чтения, вероятно, вам не хватает большого InnoDB buffer_pool. Если ЦП загружен, вероятно, ваши запросы выполняют полное сканирование таблицы вместо использования правильных индексов.
    • Настройка диска / RAID / LVM. В некоторых конкретных настройках LVM чередование может дать вам преимущество за счет выравнивания нагрузки на диск (без аппаратного RAID, подключено несколько LUNS)
    • Планировщик ввода-вывода: когда у вас есть хороший аппаратный RAID-контроллер, возможно, лучше всего подойдет noop. RedHat провел несколько тестов и они сказали, что для Oracle (и других БД) CFQ - лучший выбор. Вам нужно запустить несколько тестов (например, tpc-c или tpc-e) и выбрать, что лучше всего подходит для вашего оборудования.
    • Хорошая файловая система - ext3 плохо справляется с рабочими нагрузками, специфичными для базы данных. Лучше XFS или OCFS2. Вам снова нужны тесты.
    • Смотрите, использует ли ваша система своп. Использование подкачки снижает производительность mysql.
  2. Проверьте, правильно ли настроен ваш экземпляр MySQL / InnoDB:

    • размер буферного пула - кешировать страницы данных в памяти
    • innodb_flush_method = O_DIRECT - избегать двойной буферизации ввода-вывода
    • увеличить размер файла журнала InnoDB - для рабочей нагрузки с интенсивной записью это может улучшить производительность. Но помните: больший размер файла журнала означает более длительное восстановление после сбоя. Иногда по часам !!!
    • innodb_flush_log_at_trx_commit = 0 или 2 - если вас не беспокоит ACID, и вы можете потерять транзакции в последние секунды или две.
    • key_buffer_size - очень важно для MyISAM, но используется для дисковых временных таблиц.
    • Следи за своим СТАТУС INNODB
  3. Проанализируйте свою рабочую нагрузку - поймайте все ваши запросы в журнал медленных запросов и запустите для него mk-query-digest. Вы можете поймать все запросы, используя tcpdump и maatkit
    • На какие запросы у вас уходит больше всего серверного времени?
    • Созданы ли какие-либо временные таблицы, особенно большие временные таблицы?
    • Узнайте, как использовать объяснение
    • Ваше приложение использует транзакции? Когда вы запускаете запросы с autocommit = 1 (по умолчанию для MySQL), каждый запрос вставки / обновления начинает новую транзакцию, что вызывает некоторые накладные расходы. Если возможно, лучше отключить автокоммит (в драйвере MySQL для python автокоммит по умолчанию отключен) и вручную выполнить коммит после того, как все изменения будут сделаны.
    • Ваше приложение выполняет серию вставок в одну и ту же таблицу в цикле? Load data infile команда намного быстрее для серий вставок.
    • Помните: select count(*) from table; для innodb работает намного медленнее, чем для myisam.
    • Какие типы запросов INSERT / UPDATE занимают большую часть времени сервера? Как их можно оптимизировать?
    • Проверьте, есть ли в вашей БД правильные индексы, и при необходимости добавьте их.

В нашей среде у нас была ситуация, когда один тип запросов на обновление был медленным. Расчетное время выполнения пакетной работы - 2 дня !!! После анализа журнала медленных запросов мы обнаружили, что для выполнения этого типа запроса на обновление требуется 4 секунды. Запрос выглядел так: update table1 set field1=value1 where table1.field2=xx table2.field3=yy and table2.field4=zz. После преобразования запроса обновления в запрос выбора и выполнения объяснения этого запроса выбора мы обнаруживаем, что этот тип запроса не использует индекс. После создания правильного индекса мы сократили время выполнения запроса на обновление до миллисекунд, и вся работа была завершена менее чем за два часа.

Полезные ссылки:

С конфигурацией innoDB по умолчанию вы будете ограничены тем, насколько быстро вы можете записывать и сбрасывать транзакции на диск. Если вы можете немного потерять ACID, поэкспериментируйте с innodb_flush_log_at_trx_commit. Установите 0 для записи и сброса журнала на диск примерно каждую секунду. Установите значение 1 (по умолчанию) для записи и сброса при каждой фиксации. Установите значение 2, чтобы записывать в файл журнала после каждой фиксации, но сбрасывать только один раз в секунду.

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

Также обратите внимание на то, что делают ваши диски. RAID 10> RAID 5 для записи за счет дополнительного диска.

Примером проблем с блокировкой будет статус подключения в show full processlist;

Прочтите my.cnf и документация MySQL. Параметры конфигурации очень хорошо документированы.

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

Настройка будет зависеть от вашего предпочтительного движка базы данных и архитектуры приложения. Для поиска в Интернете есть существенные ресурсы.

Включение мониторов Innodb может помочь определить причины блокировок и взаимоблокировок:

ПОКАЗАТЬ СТАТУС INNODB ENGINE и мониторы InnoDB

InnoDB - довольно хороший движок. Однако он сильно зависит от того, чтобы его «настроили». Одна вещь заключается в том, что если ваши вставки не в порядке увеличения первичных ключей, innoDB может занять немного больше времени, чем MyISAM. Это можно легко преодолеть, установив более высокий innodb_buffer_pool_size. Я предлагаю установить его на уровне 60-70% от общего объема оперативной памяти. Сейчас я использую 4 таких сервера в производстве, вставляя около 3,5 миллионов строк в минуту. У них уже есть около 3 терабайт. InnoDB это должно было быть из-за большого количества параллельных вставок. Есть и другие способы ускорить вставку. И я проверил некоторые.

Как я решаю проблемы с производительностью вставки и обновления в MySQL в веб-приложении, просто отключив автоматическую фиксацию и зафиксировав изменения один раз в java. Как предложено в документации mysql.

Документы MySQL