Отладка запроса MySQL постоянно влияет на время выполнения - PullRequest
1 голос
/ 29 апреля 2020

Я пытаюсь отладить простой, но очень медленный запрос MySQL для таблицы с JOIN к очень большой таблице (13 м строк), большая таблица имеет несколько индексов.

Объединение очень простое c, просто соединение ID из маленькой таблицы с foreign_ID в большой таблице.

В прошлом этот запрос выполнялся быстро, однако с тех пор было добавлено много новых данных. Раньше для этого требовалось 30 мс, сейчас это занимает 5 минут.

В режиме реального времени я попытался восстановить большую таблицу с помощью команды alter, чтобы установить для нее InnoDb. Но это не имело значения.

Итак, чтобы отладить запрос, я запускаю EXPLAIN и пытаюсь удалить соединения et c, пока запрос снова не будет выполнен очень быстро.

Типы объединения начинались как ALL, eq_ref, ref и ref.

Затем, когда я снова включаю объединения и пытаюсь найти способ заставить его работать Я обнаружил, что на самом деле сейчас ОРИГИНАЛЬНЫЙ ЗАПРОС снова работает быстро.

Единственное, что изменилось, - это план выполнения запроса.

Типы соединения теперь range, eq_ref, eq_ref и ref.

Что случилось? Почему MySQL теперь обрабатывает этот же запрос иначе, чем раньше?

И как я могу заставить мой живой сервер делать это тоже? И как я могу предотвратить это в будущем?

РЕДАКТИРОВАТЬ: MySQL версия на Prod и локально 5,7

1 Ответ

0 голосов
/ 29 апреля 2020

Вы, похоже, недовольны ошибкой в ​​планировщике запросов, которая часто появляется в MySQL 5.7 и более поздних версиях. Что происходит, так это то, что планировщик запросов примет решение о неправильном плане выполнения (индексы, порядок соединения), что приводит к тому, что один и тот же запрос к одному и тому же набору данных иногда выполняется быстро (с правильным планом выполнения) или медленно (с неправильным планом выполнения). часто приводит к полному сканированию таблицы). Я видел, как это происходило при каждом развертывании MySQL 5.7 и 8.0, над которым я работал. В MySQL 5.6 и более ранних версиях и в MariaDB такого рода поведение из планировщика запросов может быть вызвано только наличием необычно большого числа индексов в таблице (10+). Поэтому, если у вас есть много индексов в одной из задействованных таблиц, стоит попытаться рационализировать их количество.

Помимо того, что количество индексов в каждой таблице должно быть настолько низким, насколько это возможно У вас есть два варианта решения этой проблемы:

1) Когда вы идентифицируете запросы, которые сталкиваются с этой ошибкой, ограничьте их, используя подсказки индекса (USE / FORCE INDEX (index_name)) и, при необходимости, STRAIGHT_JOIN, чтобы принудительно присоединиться к JOIN ordering.

2) Переключитесь на MariaDB, который, похоже, не страдает от этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...