Почему STRAIGHT_JOIN так сильно улучшает этот запрос, и что он означает, когда он пишется после ключевого слова SELECT? - PullRequest
51 голосов
/ 28 апреля 2011

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

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

Выполнение занимает около 30 секунд, что было странно, потому что, если я закомментирую соединение или предложение 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?Как определить, когда его использовать или нет?

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

Спасибо

1 Ответ

41 голосов
/ 28 апреля 2011

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

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

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

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

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

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

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

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

  1. Сгенерированные автоматическиПлан не является оптимальным и не может быть улучшен стандартными способами:

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

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

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