Огромная разница во времени выполнения запроса MySQL, тот же запрос, тот же размер результирующего набора

#mysql

#mysql

Вопрос:

в настоящее время мы наблюдаем какое-то странное поведение в отношении времени выполнения двух наших запросов. Но в качестве примера я опишу один из них.

Сам запрос не такой сложный. Он собирает небольшой набор данных на основе двух параметров. Обычно этот запрос имеет время выполнения в диапазоне 0,01 — 0,04 секунды. Если не задан определенный набор параметров, время выполнения резко увеличивается до 70-80 секунд.

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

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

Если это поможет, сам запрос выглядит следующим образом:

 select GROUP_CONCAT( m.column1 SEPARATOR '^') as export from TABLE1 b 
join TABLE2 m on b.column2 = m.column3
join TABLE3 t on b.column4 = t.column5 
where t.column6 = parameter1 and t.column7 = parameter2;
 

Этот запрос используется уже много лет и никогда не вызывал подобных проблем. Буду очень признателен за любую помощь в этом вопросе.

Обновление в отношении комментария Акинаса:

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

Выполнение проблемного запроса к копии базы данных на том же сервере не показывает длительного времени выполнения.

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

Проблематично:

 | id | select_type | table  | type   | key     | key_len | ref            | rows | Extra | 
| 1  | SIMPLE      | m      | index  | key_b   | 18      | NULL           | 75   | Using index | 
| 1  | SIMPLE      | b      | ref    | PRIMARY | 4       | db.table.index | 311  | Using index | 
| 1  | SIMPLE      | t      | eq_ref | PRIMARY | 8       | db.table.index | 1    | Using where | 
 

Нормальный:

 | id | select_type | table | type   | key     | key_len | ref            | rows | Extra | 
| 1  | SIMPLE      | t     | ref    | fk_1    | 4       | const          | 4931 | Using where | 
| 1  | SIMPLE      | b     | ref    | fk_2    | 8       | db.table.index | 2    | Using index | 
| 1  | SIMPLE      | m     | eq_ref | PRIMARY | 4       | db.table.index | 1    | NULL | 
 

Комментарии:

1. Сначала проверьте планы выполнения — когда предоставляются регулярные и проблемные значения параметров. Отличаются ли они? Затем проверьте, остается ли проблема в копиях таблиц, восстановленных на тестовом сервере — может быть, какие-то процедуры обслуживания, необходимые для ваших таблиц (анализ, оптимизация)?

2. @Akina Спасибо, я обновил вопрос, следуя вашим предложениям

3. Измените порядок предложения FROM в соответствии с «обычным» планом и добавьте STRAIGHT_JOIN .

4. @Akina Спасибо, добавление одного ПРЯМОГО соединения устранило проблему

Ответ №1:

Просто чтобы отметить это как ответ

Комментарий Акинаса, предлагающий добавить STRAIGHT_JOIN, полностью устранил проблему.

Фактическое изменение выглядит следующим образом:

 select GROUP_CONCAT( m.column1 SEPARATOR '^') as export from TABLE1 b 
STRAIGHT_JOIN TABLE2 m on b.column2 = m.column3
join TABLE3 t on b.column4 = t.column5 
where t.column6 = parameter1 and t.column7 = parameter2;
 

Это сократило время выполнения запроса с проблемными параметрами до нормального уровня. Большое вам спасибо.