Вот сценарий, который появился совсем недавно на работе.
Рассмотрим три таблицы, A, B, C.
А имеет 3000 строк; B имеет 300 000 000 строк; и C имеет 2000 строк.
Определены внешние ключи: B (a_id), B (c_id).
Предположим, у вас есть запрос, который выглядит следующим образом:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
По моему опыту, MySQL в этом случае может выбрать C -> B -> A. C меньше, чем A, а B огромен, и все они равносильны.
Проблема в том, что MySQL не обязательно учитывает размер пересечения между (C.id и B.c_id) и (A.id и B.a_id). Если соединение между B и C возвращает столько же строк, сколько B, то это очень плохой выбор; если бы начало с A отфильтровывало бы B на столько строк, сколько A, тогда это был бы гораздо лучший выбор. straight_join
может быть использован для форсирования этого порядка следующим образом:
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
Теперь a
должен быть включен до b
.
Обычно вы хотите выполнять объединения в порядке, который минимизирует количество строк в результирующем наборе. Поэтому начинать с небольшой таблицы и объединять ее так, чтобы полученное соединение также было небольшим, идеально. Вещи становятся грушевидными, если начинать с небольшого стола и соединять его с большим столом в конечном итоге размером с большой стол.
Это зависит от характеристик. Если распределение данных изменяется, расчет может измениться. Это также зависит от деталей реализации механизма соединения.
Худшие случаи, которые я видел для MySQL, когда почти требуется straight_join
или агрессивная подсказка индекса, - это запросы, которые разбивают на страницы для большого количества данных в строгом порядке сортировки с легкой фильтрацией. MySQL настоятельно предпочитает использовать индексы для любых фильтров и объединяет их по типам; это имеет смысл, потому что большинство людей не пытаются отсортировать всю базу данных, а имеют ограниченное подмножество строк, которые реагируют на запрос, и сортировка ограниченного подмножества выполняется намного быстрее, чем фильтрация всей таблицы, независимо от того, отсортирована она или нет. не. В этом случае прямое соединение сразу после таблицы, в которой был индексированный столбец, я хотел отсортировать по фиксированным вещам.