Почему STRAIGHT_JOIN так сильно улучшает этот запрос, и что это значит, когда он написан после ключевого слова SELECT? - программирование
Подтвердить что ты не робот

Почему STRAIGHT_JOIN так сильно улучшает этот запрос, и что это значит, когда он написан после ключевого слова SELECT?

У меня есть следующий запрос MySql:

select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1

Для запуска требуется около 30 секунд, что было странно, потому что, если я прокомментирую предложение join или where, это займет меньше секунды: то есть.

select t1.*
from Table1 t1
where t1.FilterID = 1

или

select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID

каждый занимает меньше секунды.

Тогда есть ключевое слово STRAIGHT_JOIN, в котором я могу найти одну ссылку, здесь: http://dev.mysql.com/doc/refman/5.0/en/join.html

STRAIGHT_JOIN похож на JOIN, за исключением того, что левая таблица всегда прочитайте перед правильным столом. Это может для тех (нескольких) случаев для который оптимизатор объединения ставит таблицы в неправильном порядке.

Что? Я могу написать:

select t1.*
from Table1 t1
STRAIGHT_JOIN  Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1

и запрос выполняется менее чем за секунду.

Даже незнакомец, я могу написать:

select STRAIGHT_JOIN  t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1

и это занимает менее секунды, и этот синтаксис не кажется даже законным.

Я бы предположил, что второй пример означает, что STRAIGHT_JOIN будет использоваться всякий раз, когда записывается INNER JOIN, но я не могу найти документацию об этом.

Что здесь происходит, и как "оптимизатор объединения" приводит к такой относительно низкой производительности? Должен ли я всегда использовать STRAIGHT_JOIN? Как я могу узнать, когда его использовать или нет?

Таблица 1 и Таблица 2 имеют целые первичные ключи; FilterID - это внешний ключ для другой таблицы; столбцы CommonID ​​являются внешними ключами к третьей таблице. У них обоих есть индексы. Ядром базы данных является InnoDB.

Спасибо

4b9b3361

Ответ 1

Что здесь происходит, и как оптимизатор объединения может привести к такой относительно низкой производительности?

STRAIGHT_JOIN заставляет порядок соединения таблиц, поэтому table1 сканируется во внешнем цикле и table2 во внутреннем цикле.

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

Должен ли я всегда использовать STRAIGHT_JOIN

Нет, только если оптимизатор ошибочен. Это может быть, если ваше распределение данных сильно искажено или не может быть правильно рассчитано (скажем, для пространственных или полнотекстовых индексов).

Как я могу узнать, когда его использовать или нет?

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

Если вы видите, что:

  • Автоматически созданный план не является оптимальным и не может быть улучшен стандартными способами,

  • Версия STRAIGHT_JOIN лучше, вы понимаете, что она всегда будет и понимает, почему она всегда будет

затем используйте STRAIGHT_JOIN.