Тестирование производительности запросов в MySQL

Я пытаюсь настроить сценарий, который будет проверять производительность запросов на сервере mysql разработки. Вот подробности:

  • У меня есть root-доступ
  • Я единственный пользователь, имеющий доступ к серверу
  • В основном интересуется производительностью InnoDB
  • Запросы, которые я оптимизирую, - это в основном поисковые запросы (SELECT ... LIKE '%xy%')

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

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

Если кто-то может подробно объяснить это поведение, я могу использовать SQL_NO_CACHE; Я действительно считаю, что это может быть связано с кешем файловой системы и / или кешированием индексов, используемых для выполнения запроса, так как это сообщение объясняет. Мне не ясно, когда буферный пул и ключевой буфер становятся недействительными или как они могут помешать тестированию.

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


person Unreason    schedule 03.05.2010    source источник
comment
Без какого-либо тестирования я могу сказать вам, что LIKE '%xy%' будет иметь ужасную производительность. Чтобы определить, работает ли один запрос лучше, чем другой, лучше использовать EXPLAIN.   -  person Your Common Sense    schedule 03.05.2010
comment
Да, я знаю, что с подобными запросами придется проводить много сравнений. Проблема в том, что запрос сложнее, и я обычно могу переписать его несколькими способами, каждый из которых работает по-разному. Моя цель - надежно измерить разницу в производительности. (EXPLAIN - хорошее предложение, и я его использую, но в дополнение к этому я хотел бы измерить «реальную» производительность).   -  person Unreason    schedule 03.05.2010


Ответы (6)


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

Некоторые вещи, которые могут быть для этого полезны:

rows столбец в результате EXPLAIN SELECT ... Потом,

mysql> set profiling=1;
mysql> select sql_no_cache * from mytable;
 ...
mysql> show profile;
+--------------------+----------+
| Status             | Duration |
+--------------------+----------+
| starting           | 0.000063 |
| Opening tables     | 0.000009 |
| System lock        | 0.000002 |
| Table lock         | 0.000005 |
| init               | 0.000012 |
| optimizing         | 0.000002 |
| statistics         | 0.000007 |
| preparing          | 0.000005 |
| executing          | 0.000001 |
| Sending data       | 0.001309 |
| end                | 0.000003 |
| query end          | 0.000001 |
| freeing items      | 0.000016 |
| logging slow query | 0.000001 |
| cleaning up        | 0.000001 |
+--------------------+----------+
15 rows in set (0.00 sec)

Потом,

mysql> FLUSH STATUS;
mysql> select sql_no_cache * from mytable;
...
mysql> SHOW SESSION STATUS LIKE 'Select%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Select_full_join       | 0     |
| Select_full_range_join | 0     |
| Select_range           | 0     |
| Select_range_check     | 0     |
| Select_scan            | 1     |
+------------------------+-------+
5 rows in set (0.00 sec)

И еще одно интересное значение - last_query_cost, которое показывает, насколько дорого оптимизатор оценил запрос (значение - это количество случайных чтений страницы):

mysql> SHOW STATUS LIKE 'last_query_cost';
+-----------------+-------------+
| Variable_name   | Value       |
+-----------------+-------------+
| Last_query_cost | 2635.399000 |
+-----------------+-------------+
1 row in set (0.00 sec)

Документация MySQL - ваш друг.

person newtover    schedule 06.05.2010
comment
Следует добавить, что last_query_cost ограничен в выводе. Если ваш запрос плоский и простой, он работает, подзапросы или UNION не пройдут эту проверку. - person John; 19.09.2017

Цитируется из этой страницы: Параметры SQL_NO_CACHE влияют на кеширование результатов запроса в кеше запроса. Если ваша таблица довольно маленькая, возможно, что сама таблица уже кэширована. Поскольку вы просто избегаете кеширования результатов, а не таблиц, вы иногда получаете описанное поведение. Итак, как сказано в других сообщениях, вам следует очистить свои таблицы между запросами.

person ablaeul    schedule 07.05.2010

Как предлагается в связанной статье, используйте FLUSH TABLES между тестовыми запусками для максимального сброса (особенно кеша запросов).

Разве ваше тестирование не должно принимать во внимание, что InnoDB сам по себе будет иметь разные состояния во время реальной производительности, так что вас интересует совокупная производительность по нескольким испытаниям? Насколько «реальным» будет ваше тестирование производительности, если вы хотите перезагружать InnoDB для каждой пробной версии? Запрос, который вы отклоняете, потому что он плохо работает сразу после перезапуска, может оказаться лучшим запросом после того, как InnoDB немного нагреется.

На вашем месте я бы сосредоточился на том, что оптимизатор запросов делает отдельно от производительности InnoDB. О том, как настроить InnoDB, много написано, но для начала полезно иметь хорошие запросы.

Вы также можете попробовать измерить производительность с помощью эквивалентных таблиц MyISAM, где FLUSH TABLES действительно вернет вас к практически идентичной начальной точке.

Вы пробовали вообще отключить кеширование запросов? Даже с SQL_NO_CACHE, простое включение кеша запросов приводит к потере около 3%.

person David M    schedule 05.05.2010

Думали ли вы об использовании Maatkit? Одна из его возможностей, с которой я немного знаком, - это захват сетевых данных MySQL с помощью tcpdump и обработка дампа с помощью mk-query-digest. Этот инструмент позволяет отображать некоторые подробные сведения о каждом запросе. Но есть целый ряд других инструментов, которые должны упростить анализ запросов.

person Bram Schoenmakers    schedule 05.05.2010
comment
Maatkit находится в моем списке инструментов для тестирования. Какие еще? - person Unreason; 06.05.2010
comment
Что ж, я, наверное, был слишком сонным, когда писал это. Я обратился к другим командам / инструментам внутри Maatkit для анализа запросов. - person Bram Schoenmakers; 06.05.2010

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

person Spidfire    schedule 05.05.2010

Полнотекстовые запросы в InnoDB выполняются медленно (LIKE "% query%"), вы ничего не можете сделать для их оптимизации. Решения варьируются от передачи той конкретной таблицы, которую вы запрашиваете, в MyISAM, чтобы вы могли создавать полнотекстовые индексы (которые innoDB не поддерживает), до денормализации строки в индексы с возможностью поиска (не рекомендуется), Doctrine ORM предоставляет простой пример того, как это архивировать: http://www.doctrine-project.org/documentation/manual/1_1/nl/behaviors:core-behaviors:searchable "Правильным" решением вашей проблемы было бы индексирование информации, в которой вы используете полнотекстовый поиск, с помощью таких решений, как Sphinx Search или Apache Solr.

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

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

Учитывайте свою рабочую нагрузку, устраняйте частые, неэффективные запросы (используйте slow_query_log в mysql, не начинайте вслепую оптимизацию запросов).

person mhughes    schedule 05.05.2010
comment
Все советы, которые согласуются с моим текущим подходом: включен журнал медленных запросов, учитываются n-граммовые движки, учитывается рабочая нагрузка, и я не оставляю без внимания кеш для производства. Тем не менее, учитывая два запроса, которые дают одни и те же строки в качестве результата, они будут выполнять то же самое после кэширования, верно? Итак, все, что осталось, - это сравнить, как бы они работали, если бы они не были кэшированы. И мне бы хотелось иметь надежный подход, который бы ответил на этот вопрос. - person Unreason; 06.05.2010
comment
Попробуй это. Два параллельных запроса, которые вернут один и тот же набор данных, наиболее вероятно, что второй займет меньше времени. И я имею в виду значительно меньше времени. Я стремлюсь к тому, чтобы производительность конкретных запросов не была прямо пропорциональна производительности приложения. Вы должны беспокоиться не только о стоимости запросов, но и о их частоте. Частый вызов дорогостоящего запроса, который правильно кэшируется, в среднем превращается в дешевый запрос. Точно так же дорогостоящий запрос, который вызывается в среднем один раз в день, является дешевым запросом с учетом стоимости / частоты. - person mhughes; 06.05.2010