У нас есть веб-приложение.
Относительно большой и старый — много кода, в котором много-много разных запросов к базе данных.
При этом мы не Google, но к серверу базы данных поступает несколько тысяч запросов в секунду.
Что ж, наше приложение, безусловно, растёт по всем направлениям — добавляются новые функции, старые становятся лучше и сложнее, растёт количество клиентов и, соответственно, растёт объём данных в базе данных.
И в один не такой уж чудесный момент мы поняли, что что-то тормозит наше приложение.
Это означает, что вам либо нужно найти, что именно нагружает базу данных, хотя может и не нагружать ее, либо, если ничего такого нет, то брать все более мощные сервера.
Стандартный совет, как узнать, что загружает MySQL, — включить журнал медленных запросов и посмотреть, какие запросы туда попадут. Но MySQL 5.7 по умолчанию поставляется с гораздо лучшим инструментом — системная схема , который агрегирует данные из схемы производительности и позволяет получить их с помощью простых запросов, буквально типа «ОК, MySQL, покажи мне топ запросов по максимальному общему времени выполнения» Во-первых, какие проблемы возникают при использовании журнала медленных запросов:
- Когда MySQL тормозит, там накапливаются сотни запросов, которые не тормозят в периоды нормальной нагрузки — например, мы время от времени видим там выборки по первичному ключу.
- Если, например, вы установите long_query_time=3, он не будет включать запрос, который выполняется за 0,5 секунды, но имеет много вызовов.
На этом введение завершается и мы переходим к использованию системной схемы и примерам того, что вы можете увидеть.
Для начала, если ваши запросы сложнее, чем «SELECT a FROM b WHERE c =Э», стоит настроить ограничения на длину текста запроса, хранящиеся в схеме производительности.
По умолчанию это 1024 — возможно, вам этого достаточно, но мне оказалось мало.
Добавьте в my.cnf:
Переменные не являются динамическими, поэтому после этого потребуется перезагрузка сервера.max_digest_length=10240 performance_schema_max_sql_text_length=10240 performance_schema_max_digest_length=10240
Это, конечно, минус.
Далее меняем максимальную отображаемую длину текста запроса в ответах sysсхемы (по умолчанию 64 — а тут вообще не понимаю, кому это будет достаточно) use sys;
update sys_config set value=10240 WHERE variable='statement_truncate_len';
Что ж, тогда можно использовать.
Ранее упомянутые топ-запросы по максимальному общему времени выполнения: mysql> select * from statement_analysis limit 10 \G
*************************** 1. row ***************************
query: SELECT `AccSettingValue` FROM `accsetting` WHERE `accsetting` .
`AccSettingName` = ?
db: mydb
full_scan:
exec_count: 2065339
err_count: 0
warn_count: 0
total_latency: 1.75 m
max_latency: 16.52 ms
avg_latency: 50.72 us
lock_latency: 48.90 s
rows_sent: 0
rows_sent_avg: 0
rows_examined: 0
rows_examined_avg: 0
rows_affected: 0
rows_affected_avg: 0
tmp_tables: 0
tmp_disk_tables: 0
rows_sorted: 0
sort_merge_passes: 0
digest: 229c950384bddbaa0e537f54beaa1ac4
first_seen: 2018-03-19 20:20:43
last_seen: 2018-03-21 12:27:21
На примере этого запроса мы видим, что значения %_latency возвращаются в удобочитаемой форме, что удобно для чтения результата, но неудобно, если вы хотите отсортировать по ним.
Для этого все таблицы в схеме sys имеют двойники вида x$table_name.
Пример запросов, отсортированных по avg_latency, создающих временные таблицы на диске, будет выглядеть примерно так: mysql> select * from x$statement_analysis WHERE tmp_disk_tables > 0 ORDER BY avg_latency DESC limit 10 \G
Еще пара примеров полезных вещей, которые вы можете увидеть, используя sys-схему.
Запросы, среднее время выполнения которых входит в топ-5%: mysql> select * from statements_with_runtimes_in_95th_percentile LIMIT 10\G
Запросы, создающие временные таблицы: mysql> select * from statements_with_temp_tables limit 10\G
Запросы, выполняющие полное сканирование таблицы mysql> select * from statements_with_full_table_scans limit 10\G
Неиспользуемые индексы (сервер должен работать достаточно долго, чтобы этим данным можно было доверять): mysql> select * from schema_unused_indexes limit 10;
Это то, что лично мне было наиболее полезно, если интересно - есть подробная документация и примеры использования.
на GitHub или в официальная документация .
Теги: #MySQL #производительность mysql #MySQL
-
Ноутбук Тошиба
19 Oct, 24 -
Неудачная Статья Об Ускорении Отражения
19 Oct, 24 -
Менеджер Фар – Старый Друг Лучше Двух Новых
19 Oct, 24 -
3D-Движок На Основе Js + Холст
19 Oct, 24