한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Анатомия игровых лагов › L12 База данных

Замедление запроса из-за смены плана выполнения Query plan regression (stats, parameter sniffing)

ID причины db-plan-flip · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера

Открыть карточку в основной версии с иллюстрациями и экспериментами →

Код не менялся, но если БД меняет способ выполнения того же запроса (план выполнения), вчерашний запрос на 2 ms сегодня занимает сотни ms.

Почему Автоматическое обновление статистики, перезапуск БД или изменение распределения данных заставляют БД построить план заново → Следствие Выбирается план без индекса, тот же запрос становится медленнее в десятки или сотни раз и надолго занимает соединения → На экране Деплоя не было, но загрузка в какой-то функции внезапно замедляется, и ждут даже другие запросы

Симптомы
Задержка ввода, Ошибка входа / бесконечная загрузка
Факторы
Задержка, Остановка
У кого
Только одна функция, Весь сервер
Когда
Изредка, случайно
Ответственные
Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Запросы, у которых число результатов сильно зависит от значения параметра, разделять или рассмотреть подсказки плана, проектировать запросы так, чтобы они гарантированно использовали индекс.
Команда инфраструктуры: задачи
Следить за медленными запросами и записями планов выполнения, фиксировать хорошие планы (хранилище запросов SQL Server и др.), управлять временем обновления статистики.
На графике
Ступенька вверх с определённого момента · среднее время выполнения по запросам
Где смотреть
Периодически собирать среднее время запросов одного вида и смотреть динамику. В MySQL это AVG_TIMER_WAIT в events_statements_summary_by_digest, в PostgreSQL mean_exec_time в pg_stat_statements (в 12 и ниже mean_time). Планы выполнения до и после замедления сравнивать через EXPLAIN или auto_explain в PostgreSQL, в SQL Server через представление «Регрессированные запросы» (Regressed Queries) хранилища запросов
Подтверждает
В отсутствие деплоя среднее время одного запроса ступенькой вырастает в несколько десятков раз, этот момент совпадает с обновлением статистики или перезапуском БД, и план выполнения изменился
Опровергает
Если план выполнения тот же, а запрос замедлился, дело в росте данных, ожидании блокировок (db-hot-row) или диске
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
SQL Server повторно использует план, построенный под первое пришедшее значение (прослушивание параметров, parameter sniffing). Если план, построенный для нового персонажа с несколькими предметами, применяется к старому персонажу с десятками тысяч предметов, запрос сильно замедляется, и обратная ситуация тоже частая. Когда перезапуск очищает планы, всё приходит в норму, а потом может снова испортиться.

Источники

  1. Query Processing Architecture Guide Microsoft SQL Server
    Прослушивание параметров: план выполнения строится под значения параметров, переданные при компиляции или перекомпиляции
  2. Parameter Sensitive Plan Optimization Microsoft SQL Server
    Если данные распределены неравномерно, один закэшированный план подходит не для всех значений параметров
  3. Monitor performance by using the Query Store Microsoft SQL Server
    Изменения статистики, схемы или индексов меняют план, а кэш планов хранит только последний план. Принудительный план в хранилище запросов фиксирует хороший план, представление «Регрессированные запросы» (Regressed Queries) позволяет сравнить замедлившиеся запросы и их планы
  4. Statement Summary Tables MySQL
    events_statements_summary_by_digest: по каждому виду запроса COUNT_STAR и AVG_TIMER_WAIT (среднее время)
  5. pg_stat_statements — track statistics of SQL planning and execution PostgreSQL
    По каждому оператору calls, total_exec_time, mean_exec_time (среднее время выполнения)
  6. pg_stat_statements (PostgreSQL 12 Documentation) PostgreSQL
    До версии 12 включительно столбцы называются total_time и mean_time
  7. auto_explain — log execution plans of slow queries PostgreSQL
    Пишет в лог план выполнения запросов дольше auto_explain.log_min_duration

Смотрите также

Тот же слой: L12 База данных

Причины с тем же симптомом (Задержка ввода) на других слоях

Карточка в основной версии с иллюстрациями и экспериментами