Когда мне следует отдавать предпочтение JOIN, а не WHERE в запросах MySQL? - PullRequest
0 голосов
/ 09 ноября 2010

Изучите следующий сценарий (источник: http://phpweby.com/tutorials/mysql/32):

mysql> SELECT * FROM products;
+----+--------------+--------------+
| id | product_name | manufacturer |
+----+--------------+--------------+
|  1 | Shoes        | Company1     |
|  2 | Laptop       | Company2     |
|  3 | Monitor      | Company3     |
|  4 | DVD          | Company4     |
+----+--------------+--------------+

mysql> SELECT * FROM buyers;
+----+------+------------+----------+
| id | pid  | buyer_name | quantity |
+----+------+------------+----------+
|  1 |    1 | Steve      |        2 |
|  2 |    2 | John       |        1 |
|  3 |    3 | Larry      |        1 |
|  4 |    3 | Michael    |        5 |
|  5 | NULL | Steven     |     NULL |
+----+------+------------+----------+

Предположим, я хотел бы создать одну таблицу, в которой каждый покупатель указан в списке товаров, которые он купил. Я могу получить очень похожие результаты, используя два разных способа - один с использованием JOIN, а другой с использованием WHERE.

mysql> SELECT buyer_name, quantity, product_name
 FROM buyers LEFT JOIN products 
 ON buyers.pid=products.id;
+------------+----------+--------------+
| buyer_name | quantity | product_name |
+------------+----------+--------------+
| Steve      |        2 | Shoes        |
| John       |        1 | Laptop       |
| Larry      |        1 | Monitor      |
| Michael    |        5 | Monitor      |
| Steven     |     NULL | NULL         |
+------------+----------+--------------+

mysql> SELECT buyers.buyer_name, buyers.quantity, products.product_name
 FROM buyers,products 
 WHERE buyers.pid=products.id;
+------------+----------+--------------+
| buyer_name | quantity | product_name |
+------------+----------+--------------+
| Steve      |        2 | Shoes        |
| John       |        1 | Laptop       |
| Larry      |        1 | Monitor      |
| Michael    |        5 | Monitor      |
+------------+----------+--------------+

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

Но когда речь идет о больших таблицах, есть ли разница в эффективности между этими двумя запросами? Из некоторых испытаний, которые я сделал, я думаю, что есть.

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

Ответы [ 8 ]

2 голосов
/ 09 ноября 2010

Явное упоминание объединения, как правило, должно быть лучше (и его легче читать), помимо того, что оно является стандартом ANSI, но с современными оптимизаторами я не думаю, что есть какая-либо заметная разница в производительности в обеих версиях.

Примечание: два упомянутых вами запроса не эквивалентны - если вы замените левое соединение внутренним соединением, они станут эквивалентными, и в этом случае не будет заметной разницы в производительности.

Внутреннее соединение обычно быстрее, чем левое соединение.

1 голос
/ 09 ноября 2010

Вообще говоря, объединения выполняются медленно, а перекрестные - еще медленнее.

Любая система управления базами данных может оптимизировать любой тип запроса, если она предназначена для этого.Однако много-много человеко-часов было потрачено на оптимизацию соединений в любой СУБД, которая широко использовалась в течение любого промежутка времени.Итак, вообще говоря, где JOIN - это логический способ связать входные таблицы в вашем наборе результатов, используйте JOIN.WHERE имеет множество других применений.

Редактировать (для ясности по одному пункту):

MySQL существует достаточно долго, чтобы он , вероятно, оптимизировалСинтаксис перекрестного соединения WHERE должен выполняться так же, как и синтаксис JOIN, хотя в данный момент у меня нет возможности проверить установку.Итак, если разница только семантическая, скажите, что вы имеете в виду, и что будет самым ясным, что, как отмечали другие, обычно будет синтаксисом JOIN.

1 голос
/ 09 ноября 2010

Ваш второй запрос фактически эквивалентен:

SELECT buyers.buyer_name, buyers.quantity, products.product_name
FROM buyers
INNER JOIN products ON buyers.pid=products.id
;

Разница в результатах - это разница между ВНУТРЕННИМ и ВНЕШНИМ объединением.

Что касается стиля, который вы используете, это вопрос предпочтений. Большинство людей предпочитают явные объединения (синтаксис JOIN / ON) неявным соединениям (в предложении WHERE), чтобы отделить условие соединения от критериев выбора.

1 голос
/ 09 ноября 2010

Два ваших примера кода выполняют разные виды JOIN.Первый - это соединение LEFT OUTER - «внешнее» подразумевает, что оно включает результаты, которые не отображаются в обеих таблицах.Второй - это соединение INNER - оно не включает строки, которые имеют значение NULL в одной или обеих таблицах.

Я полагаю, что второй пример должен выполнить то же самое, что и «ИЗ покупателей объединяются продукты на покупателей.= products.id».

1 голос
/ 09 ноября 2010

Я бы придерживался стиля ANSI (используя ключевое слово join) синтаксис соединения. Это значительно облегчает чтение запроса.

Редактировать: Причина, по которой ваши результирующие наборы отличаются, заключается в том, что вы использовали левое соединение, которое не эквивалентно синтаксическому соединению "где".

0 голосов
/ 10 ноября 2010

Когда мне следует отдавать предпочтение JOIN, а не WHERE в запросах MySQL?

В общем, выбирайте любую конструкцию, которая логически логична: ее легко понять человеку, использующей стандартные конструкции и синтаксисупрощение переноса на будущие выпуски того же продукта или другого продукта SQL), простота обслуживания и т. д. Затем проверьте производительность и при необходимости оптимизируйте, однако оставьте исходный код в комментариях на случай, если «идеальный» код из логическоготочка зрения дает приемлемую производительность после порта.

0 голосов
/ 09 ноября 2010

Я не могу с уверенностью сказать, является ли JOIN'ing более быстрым или медленным, или эквивалентным WHERE'ing.

Однако вот как я об этом думаю - когда вы ПРИСОЕДИНЯЕТЕСЬ, вы обычно имеете дело с первичными и внешними ключами. "Продукт ВНУТРЕННЕЕ СОЕДИНЕНИЕ Покупатели на Product.id = Buyers.pid" из вашего примера.

В вашем предложении WHERE часто вы определяете другие критерии, которые не имеют никакого отношения к объединению двух таблиц. Где пункты обычно имеют дело с 1 таблицей. Например, "WHERE DateCreated> '2010/01/01' AND Status = 'A'".

Эти абстракции не всегда верны.

Я часто хочу получить все дочерние записи, где внешний ключ является конкретным значением. "WHERE investors.pid = 3" Итак, очевидно, что предложение WHERE имеет дело со значением ключа.

По моему опыту, использование предложения WHERE для объединения таблиц было популярно примерно 10-12 лет назад, а затем большинство из них перешли на использование INNER JOIN. Вот как большая часть кода, который я пишу и вижу, написанного в наши дни, структурирована, но вряд ли это хороший ответ на ваш вопрос, просто наблюдение за соглашениями.

0 голосов
/ 09 ноября 2010

Ваш вопрос немного искажен. Вы сравниваете LEFT JOIN с запросом, который копирует INNER JOIN. Однако, если бы он был написан правильно, ответом было бы, что производительность не должна быть одинаковой, INNER JOIN позволяет печатать меньше.

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