mysql - Как принудительно изменить порядок оценки внутреннего объединения? - PullRequest
0 голосов
/ 17 декабря 2018

Итак, у меня есть две таблицы: tableA и tableB.После простого внутреннего объединения этих таблиц

SELECT *
FROM tableA 
JOIN tableB
ON tableA.columnA = tableB.id

Теперь tableA содержит 29000+ строк, тогда как tableB содержит только 11000+ строк.tableB.id - это первичный ключ, следовательно, кластеризованный.И существует некластеризованный индекс на columnA.

По моему мнению, оптимизатор запросов должен обрабатывать tableB как внутреннюю таблицу при выполнении объединения, поскольку она имеет меньшее количество строк, а tableA как внешнюю таблицу, как многострок необходимо отфильтровать от tableA на основе значения столбца tableB.id.

Но на самом деле происходит полная противоположность этому.По какой-то причине оптимизатор запросов обрабатывает tableA как внутреннюю таблицу и tableB как внешнюю таблицу.

Может кто-нибудь объяснить, почему это происходит и какую ошибку я совершаю в своем мыслительном процессе?Кроме того, есть ли способ принудительно заменить решение оптимизатора запросов и предписать ему обрабатывать tableB как внутреннюю таблицу?Мне просто любопытно посмотреть, как два разных выполнения одного и того же запроса сравниваются друг с другом.Спасибо.

1 Ответ

0 голосов
/ 17 декабря 2018

В InnoDB поиск индекса первичного ключа несколько эффективнее поиска вторичного индекса.Оптимизатор, вероятно, предпочитает запускать объединение, которое выполняет поиск по tableB.id, поскольку использует индекс первичного ключа.

Если вы хотите переопределить способность оптимизатора переупорядочивать таблицы, вы можете использовать подсказку оптимизатора.Доступ к таблицам будет осуществляться в порядке, указанном вами в запросе.

SELECT *
FROM tableA 
STRAIGHT_JOIN tableB
ON tableA.columnA = tableB.id

Этот синтаксис должен работать в любой поддерживаемой в настоящее время версии MySQL.

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

В MySQL 8.0 также есть новый синтаксис для указания порядка соединения с большим контролем: https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html#optimizer-hints-join-order

...