Где лучше поставить "включенные" условия в нескольких соединениях? (MySQL)
У меня есть несколько объединений, включая левые соединения в MySQL. Есть два способа сделать это.
Я могу поставить условия "ВКЛ" сразу после каждого соединения:
выберите * из A соедините B ON (A.bid = B.ID) соедините C ON (B.cid = C.ID) соедините D ON (c.did = D.ID)
Я могу поместить их все в одно предложение "ON":
выбрать * из A объединить B присоединиться к C присоединиться к D ON (A.bid = B.ID AND B.cid = C.ID AND c.did = D.ID)
Какой способ лучше?
Отличается ли мне необходимость левого или правого соединения в моем запросе?
2 ответа
Для простых применений MySQL почти неизбежно будет выполнять их одинаково, поэтому это способ предпочтения и удобочитаемости (что является отличным предметом обсуждения).
Однако с более сложными запросами, особенно с OUTER JOIN
Те, которые могут стать дисковыми и io-связанными, могут иметь производительные и невидимые последствия, если не использовать предложение WHERE с запросами OUTER JOIN.
Разница между запросом, который выполняется в течение 8 минут или 0,8 секунды, может в конечном итоге зависеть от WHERE
предложение, особенно в отношении индексов ( как MySQL использует индексы): WHERE
Предложение является основной частью предоставления оптимизатору запросов информации, необходимой ему для выполнения своей работы, и сообщает движку, как выполнить запрос наиболее эффективным способом.
Из того, как MySQL оптимизирует запросы, используя WHERE:
"В этом разделе обсуждаются оптимизации, которые могут быть сделаны для обработки предложений WHERE... Лучшая комбинация объединения для объединения таблиц находится при использовании всех возможностей. Если все столбцы в предложениях ORDER BY и GROUP BY взяты из одной и той же таблицы, эта таблица предпочтительнее при присоединении."
Для каждой таблицы в соединении создается более простая WHERE, чтобы получить быструю оценку WHERE для таблицы, а также как можно скорее пропустить строки
Некоторые примеры:
Полное сканирование таблицы (тип = ВСЕ) с НЕТ Using where
в ЭКСТРА
[SQL] SELECT cr.id,cr2.role FROM CReportsAL cr
LEFT JOIN CReportsCA cr2
ON cr.id = cr2.id AND cr.role = cr2.role AND cr.util = 1000
[Err] Out of memory
Пользы where
оптимизировать результаты, с индексом ( Using where
, Using index
):
[SQL] SELECT cr.id,cr2.role FROM CReportsAL cr
LEFT JOIN CReportsCA cr2
ON cr.id = cr2.id
WHERE cr.role = cr2.role
AND cr.util = 1000
515661 rows in set (0.124s)
**** Сочетание ON/WHERE - тот же результат - тот же план в EXPLAIN
*******
[SQL] SELECT cr.id,cr2.role FROM CReportsAL cr
LEFT JOIN CReportsCA cr2
ON cr.id = cr2.id
AND cr.role = cr2.role
WHERE cr.util = 1000
515661 rows in set (0.121s)
MySQL, как правило, достаточно умен, чтобы разбираться с простыми запросами, подобными приведенным выше, и выполнять их аналогично, но в некоторых случаях это не так.
Производительность внешнего запроса соединения:
Поскольку как левое, так и правое соединение являются внешними соединениями ( здесь подробно рассмотрены вопросы), возникает проблема декартового произведения, поэтому следует избегать обхода табличных сканирований, чтобы как можно больше строк, ненужных для запроса, удалялось как можно быстрее. насколько это возможно.
WHERE
Индексы и оптимизатор запросов, используемые вместе, могут полностью устранить проблемы, связанные с декартовыми продуктами, при осторожном использовании с агрегатными функциями, такими как AVERAGE
, GROUP BY
, SUM
, DISTINCT
и т. д. порядок уменьшения времени выполнения достигается при правильной индексации пользователем и использовании предложения WHERE.
в заключение
Опять же, для большинства запросов оптимизатор запросов будет выполнять их таким же образом - делая это способом предпочтения, но когда оптимизация запросов становится важной, WHERE
это очень важный инструмент. Я видел некоторое увеличение производительности в некоторых случаях с INNER JOIN
указав индексированное col в качестве дополнительного предложения ON..AND ON, но я не могу сказать вам, почему.
Поместите предложение ON в соединение, к которому оно относится.
Причины:
- удобочитаемость: другие могут легко увидеть, как соединяются таблицы
- производительность: если вы оставите условия позже в запросе, вы получите гораздо больше соединений, чем нужно - это все равно что поместить условия в предложение where
- соглашение: следуя обычному стилю, ваш код будет более переносимым и с меньшей вероятностью столкнется с проблемами, которые могут возникнуть с необычным синтаксисом - делайте то, что работает