Запросы MySQL в моей производственной среде занимают гораздо больше времени, чем я ожидал. Рассматриваемый сайт является довольно большим сайтом Drupal с множеством установленных модулей. Веб-сервер (Nginx) и сервер базы данных (mysql) размещены на отдельных машинах, подключенных к локальной сети со скоростью 100 Мбит / с (размещенной на Rackspace).
У меня на ноутбуке запущен точно такой же сайт для разработки. Очевидно, что на моем ноутбуке веб-сервер и сервер базы данных находятся в одном корпусе.
Вот результаты моих запросов к базе данных:
Производство:
Выполнен 291 запрос за 320,33 миллисекунды. (домашняя страница)
Выполнено 517 запросов за 999,81 миллисекунды. (страница содержания)
Развитие:
Выполнено 316 запросов за 46,28 миллисекунды. (домашняя страница)
Выполнено 586 запросов за 79,09 миллисекунды. (страница содержания)
Как ясно видно из этих результатов, время, затрачиваемое на запрос к базе данных MySQL, намного короче на моем ноутбуке, где сервер MySQL работает в той же базе данных, что и веб-сервер.
Почему это?!
Одним из факторов должна быть задержка в сети. В среднем обход от веб-сервера до сервера базы данных занимает 0,16 мс (показано с помощью команды ping). Это должно быть добавлено к каждому отдельному запросу MySQL. Итак, возьмем приведенный выше пример страницы с контентом, где выполнено 517 запросов. Только сетевая задержка добавит 82 мс к общему времени запроса. Однако это не учитывает разницу, которую я вижу (79 мс на моем ноутбуке против 999 мс на производственной коробке).
На какие еще факторы мне следует обратить внимание? Я думал об обновлении сетевой карты до гигабитного соединения, но очевидно, что здесь нужно кое-что еще.
Я запустил сценарий настройки производительности MySQL из http://www.day32.com/MySQL/ и он говорит мне, что мой сервер базы данных настроен хорошо (по-видимому, лучше, чем мой ноутбук). Сообщается только о проблеме: «Из 4394 временных таблиц 48% были созданы на диске». Это верно как для среды, так и для производственной среды. Я даже попытался увеличить max_heap_table_size и Current tmp_table_size до 1 ГБ без каких-либо изменений (я думаю, это потому, что у меня есть столбцы BLOB и TEXT).
Это потому, что, если БД не находится на том же сервере, что и интерфейс, вам нужно выполнять круговой обход для каждого запроса (возможно, больше, в зависимости от размера ответа). Проверка связи с другим сервером в том же центре обработки данных может занять до 1 мс. Намного меньше, если два сервера находятся в одной стойке, но 1 мс - хорошее практическое правило.
Это означает, что для ~ 300 небольших запросов вы должны ожидать ~ 300 мсек, что довольно близко к тому, что вы видите.
Если два сервера находятся на одном компьютере, вам нужно только переключить контекст между процессами, чтобы переместить данные из процесса БД во внешний интерфейс. Обычно переключение контекста (со всеми типичными сбросами) занимает ~ 40 мкс (в очень широком смысле), и вам понадобится по крайней мере пара из них (интерфейс запрашивает данные, БД читает запросы и подготавливает и обслуживает данные, а интерфейс считывает обратно данные). Поэтому я ожидал бы ~ 80 мкс для каждого запроса (давайте округлим его до 0,1 мс, чтобы упростить математику). Таким образом, вы можете ожидать ~ 30 мс для 300 небольших запросов, что также довольно близко к тому, что вы видите.
Трудно дать однозначный ответ. Я действительно не думаю, что сеть является узким местом, ну, если только у вас не очень большой трафик на сервере.
У вас одинаковая точная конфигурация как на машине разработки, так и на рабочем сервере?
Вы уверены, что все индексы были успешно созданы на рабочем сервере?
Это может быть объем данных на вашем производственном сервере. Я имею в виду, что для сравнения результатов между производственной машиной и машиной для разработки у вас должно быть одинаковое количество строк в таблицах, так ли это?
Использовали ли вы одни и те же установочные файлы для установки MySQL на машине разработки и на рабочем сервере? Я имею в виду, есть ли у вас одна и та же версия MySQL на машинах для разработки и производства? Это для той же ОС? Также 32-битный или 64-битный? Вероятно, ошибка в версии MySQL, установленной на сервере.
Возможности безграничны, без более подробной информации будет действительно сложно дать информативный ответ.
Что бы я сделал, чтобы определить, где находится узкое место: я бы провел профилирование запроса: http://dev.mysql.com/doc/refman/5.0/en/show-profiles.html
Если числа намного ниже, чем то, что вы можете увидеть из того же запроса, который вы выполняете на своем веб-сервере, то это проблема «транспорта». (Задержка сети Rackspace, конфигурация коммутатора, большие наборы данных (ВЫБРАТЬ *) с TEXT
/BLOB
возвращенные поля и т. д.)
Если числа почти одинаковы, вам нужно оптимизировать запросы и улучшить файл конфигурации. Вот ссылка, которая может помочь: https://stackoverflow.com/questions/1191067/how-to-test-mysql-query-speed-with-less-inconsistencies/1191506#1191506
Кстати, когда мой сервер перешел со 100 Мбайт на 1 Гбайт, прирост производительности был потрясающим!
Включено ли кеширование запросов? Посмотрите на результат:
SHOW VARIABLES LIKE 'query_cache_size';
Если он больше нуля, он включен. Это существенно повлияет на производительность веб-сайта, поддерживаемого MySQL, хотя я не уверен, связано ли это с вашей конкретной проблемой здесь.
Я не думаю, что есть какой-либо способ захватить набор запросов и запустить их из логина на сервере базы данных MySQL, чтобы увидеть, что там по-другому?
Другая возможная проблема заключается в том, что если вы не выполняете кеширование сеанса, вы открываете новый сеанс каждый раз, когда делаете вызов базы данных. Вы знаете, кешируете ли вы сеанс? Открытие нового сеанса для каждого вызова может дорого обойтись в сети.
Сообщается только о проблеме: «Из 4394 временных таблиц 48% были созданы на диске». Это верно как для среды, так и для производственной среды. Я даже попытался увеличить max_heap_table_size и Current tmp_table_size до 1 ГБ без каких-либо изменений (я думаю, это потому, что у меня есть столбцы BLOB и TEXT).
Вы можете поместить MySQLs tmpdir в файловую систему на основе RAM (например, tmpfs), чтобы повысить производительность.
Ура
P.S.
Возможно, снижение производительности связано с записью RAID в производственной среде.
Установка и отключение TCP-соединения намного дороже, чем соединение через сокет при работе на localhost. Проверьте, сколько подключений к базе данных инициируется при загрузке страницы.