Почему MySQL изменил бы тип соединения при запросе в разных базах данных

#mysql

#mysql

Вопрос:

У нас разные RDS (AWS, GCP и т. Д.), И у этих RDS много баз данных. Каждая из наших баз данных создается и управляется одним и тем же внутренним кодом, и, следовательно, все таблицы и наборы данных совпадают.

У меня есть запрос, который, когда я запускаю в одной БД, он останавливается, и сравнение explain показывает, что он обрабатывается по-разному.

Итак, для этого примера у меня есть first_table, а у этого FK — значение second_table. Все индексы и т. Д. Правильно сформированы. И теперь допустим, что у меня есть db_one на нашем AWS RDS, и мы db_two и db_three на нашем сервере базы данных GCP.

first_table на db_one составляет 2 ГБ, db_two — 8,8 ГБ, db_three — 20 МБ. second_table, к которому мы подключаемся, составляет всего 64 КБ.

 select * from first_table a
where first_table a.my_date between '2020-12-01 00:00:00' and '2020-12-01 00:00:00';
 

Если я запускаю это для каждой базы данных, выполнение и возврат запроса занимает менее секунды. В db_two из-за размера передача данных по сети мне занимает несколько дополнительных секунд — это нормально и ожидаемо.

Когда я запускаю explain это, он говорит «тип: диапазон, таблица: a». Это согласуется со всеми базами данных.

Теперь, когда я добавляю FK join и запускаю на db_one. Это так же мгновенно.

 select * from first_table a
join second_table b on b.ft_id = a.id
where first_table a.my_date between '2020-12-01 00:00:00' and '2020-12-01 00:00:00';
 

Однако, когда я запускаю это на db_two (самом большом), оно никогда не заканчивается.
Теперь, когда я запускаю explain на обеих базах данных, они разные.

В db_one он по-прежнему использует «тип: диапазон, таблица: a» и «тип: eq_ref, таблица: b»

В db_two теперь написано: «таблица: b, тип: ALL, таблица: a, тип: ref»

Поэтому я подумал, что, возможно, между этими RDS есть разница или что-то в этом роде, поэтому я запустил запрос и объяснение на db_three (который находится на том же сервере, что и db_two), он запустился мгновенно, и объяснение было таким же, как на db_one.
Фактически я запустил объяснение на всех наших RDS в разных базах данных, и это всегда было так, как я ожидал: «таблица: a, тип: диапазон. таблица: b, тип: eq_ref».

Только в db_two, с самой большой таблицей, объяснение отличается, но также приводит к очень низкой производительности.

Кто-нибудь может помочь объяснить, почему это происходит? Или что является причиной этого, и могу ли я обойти это?

Мое текущее решение — просто запустить быстрый sql с одной таблицей и вернуться к python, затем извлечь данные FK и вручную сшить и отсортировать их самостоятельно. По крайней мере, это сработало бы.
Но это кажется сумасшедшим.

Надеюсь, я что-то здесь не понимаю.

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

1. План выполнения строится каждый раз, когда вы выполняете запрос. Основой для этого является статистика таблицы. Если он слишком старый и / или неточный, может быть построен неправильный план выполнения. Вы можете: обновить статистику, принудительно ввести некоторый индекс, добавить straight_join…

2. обновить статистику: я попробовал ПРОАНАЛИЗИРОВАТЬ ТАБЛИЦУ, и это не помогло. «straight_join» сработал! Я никогда не слышал об этом раньше. Но принудительное «сначала прочитать левую таблицу» является массовым. Спасибо