В каком порядке оцениваются соединения MySQL? - PullRequest
26 голосов
/ 23 октября 2008

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

SELECT c.*
FROM companies AS c
JOIN users AS u USING(companyid)
JOIN jobs AS j USING(userid)
JOIN useraccounts AS us USING(userid)
WHERE j.jobid = 123;

У меня есть следующие вопросы:

  1. Является ли синтаксис USING синонимом синтаксиса ON?
  2. Оцениваются ли эти объединения слева направо? Другими словами, говорит ли этот запрос: x = companies JOIN users; y = x JOIN вакансии; z = y ПРИСОЕДИНЯЙТЕСЬ к учетным записям;
  3. Если ответ на вопрос 2 положительный, можно ли предположить, что в таблице companies есть столбцы companyid, userid и jobid?
  4. Я не понимаю, как можно использовать предложение WHERE для выбора строк в таблице компаний, когда она ссылается на псевдоним "j"

Буду признателен за любую помощь!

Ответы [ 7 ]

26 голосов
/ 23 октября 2008
  1. ИСПОЛЬЗОВАНИЕ (имя поля) - это сокращенный способ сказать ON table1.fieldname = table2.fieldname.

  2. SQL не определяет «порядок», в котором выполняются СОЕДИНЕНИЯ, потому что это не характер языка. Очевидно, в заявлении должен быть указан порядок, но ВНУТРЕННЕЕ СОЕДИНЕНИЕ можно считать коммутативным: вы можете перечислить их в любом порядке, и вы получите те же результаты.

    Тем не менее, при построении SELECT ... JOIN, особенно в том, который включает в себя LEFT JOIN, я обнаружил, что имеет смысл рассматривать третье JOIN как соединение новой таблицы с результатами первого JOIN, четвертого JOIN как присоединение к результатам второго JOIN и т. д.

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

  3. Нет. При сборке запроса требуется, чтобы у компаний и пользователей был и идентификатор компании, и у заданий есть идентификатор пользователя, и идентификатор задания, а у учетной записи пользователя есть идентификатор пользователя. Однако только одна из компаний или нуждается в ИД пользователя для работы JOIN.

  4. Предложение WHERE фильтрует весь результат, т. Е. Все объединенные столбцы, используя столбец, предоставленный таблицей заданий.

11 голосов
/ 23 октября 2008

Я не могу ответить немного о синтаксисе USING. Это странно. Я никогда раньше этого не видел, вместо этого всегда использовал предложение ON.

Но я могу сказать вам, что порядок операций JOIN определяется динамически оптимизатором запросов, когда он строит свой план запросов на основе системы эвристики оптимизации, некоторые из которых:

  1. Выполняется ли соединение в поле первичного ключа? Если это так, это получает высокий приоритет в плане запроса.

  2. Выполняется ли соединение в поле внешнего ключа? Это также получает высокий приоритет.

  3. Существует ли индекс в объединенном поле? Если это так, увеличьте приоритет.

  4. Выполняется ли операция JOIN над полем в предложении WHERE? Можно ли оценить выражение предложения WHERE, изучив индекс (а не выполнив сканирование таблицы)? Это основная возможность оптимизации, поэтому она получает значительный приоритет.

  5. Какова мощность объединенного столбца? Столбцы с большим количеством элементов дают оптимизатору больше возможностей для выявления ложных совпадений (тех, которые не удовлетворяют предложению WHERE или предложению ON), поэтому объединения с большим количеством элементов обычно обрабатываются до соединений с низким числом элементов.

  6. Сколько фактических строк в объединенной таблице? Объединение с таблицей, содержащей только 100 значений, приведет к меньшему взрыву данных, чем объединение с таблицей с десятью миллионами строк.

Во всяком случае ... дело в том ... что есть много переменных, которые входят в план выполнения запроса. Если вы хотите увидеть, как MySQL оптимизирует свои запросы, используйте синтаксис EXPLAIN.

И вот хорошая статья для чтения:

http://www.informit.com/articles/article.aspx?p=377652


В режиме редактирования:

Чтобы ответить на ваш 4-й вопрос: вы не запрашиваете таблицу компаний. Вы запрашиваете объединенный кросс-продукт ALL четырех таблиц в своих предложениях FROM и USING.

Псевдоним "j.jobid" - это просто полное имя одного из столбцов в этой объединенной коллекции таблиц.

2 голосов
/ 15 апреля 2009

В MySQL часто интересно спросить оптимизатора запросов, что он планирует делать, с помощью:

EXPLAIN SELECT [...]

См. "7.2.1 Оптимизация запросов с помощью EXPLAIN"

0 голосов
/ 05 января 2018

Вот более подробный ответ о приоритете JOIN. В вашем случае все JOIN являются коммутативными. Давайте попробуем тот, где их нет.

Схема сборки:

CREATE TABLE users (
  name text
);

CREATE TABLE orders (
  order_id text,
  user_name text
);

CREATE TABLE shipments (
  order_id text,
  fulfiller text
);

Добавить данные:

INSERT INTO users VALUES ('Bob'), ('Mary');

INSERT INTO orders VALUES ('order1', 'Bob');

INSERT INTO shipments VALUES ('order1', 'Fulfilling Mary');

Выполнить запрос:

SELECT *
  FROM users
       LEFT OUTER JOIN orders
       ON orders.user_name = users.name
       JOIN shipments
       ON shipments.order_id = orders.order_id

Результат:

Возвращается только строка Боба

Анализ:

В этом запросе LEFT OUTER JOIN был оценен первым, а JOIN - по составному результату LEFT OUTER JOIN.

Второй запрос:

SELECT *
  FROM users
       LEFT OUTER JOIN (
         orders
         JOIN shipments
         ON shipments.order_id = orders.order_id)
         ON orders.user_name = users.name

Результат:

Одна строка для Боба (с данными выполнения) и одна строка для Мэри с NULL для данных исполнения.

Анализ:

Скобка изменила порядок оценки.


Дополнительная документация по MySQL: https://dev.mysql.com/doc/refman/5.5/en/nested-join-optimization.html

0 голосов
/ 23 октября 2008

1) Использование не совсем то же самое, что и on, но это короткая рука, где в обеих таблицах есть столбец с тем же именем, к которому вы присоединяетесь ... см .: http://www.java2s.com/Tutorial/MySQL/0100__Table-Join/ThekeywordUSINGcanbeusedasareplacementfortheONkeywordduringthetableJoins.htm

На мой взгляд, читать сложнее, поэтому я бы стал разбирать объединения.

3) Из этого запроса не ясно, но я бы предположил, что это не так.

2) Предполагая, что вы объединяете другие таблицы (не все напрямую в компаниях), порядок в этом запросе имеет значение ... см. Сравнение ниже:

оригинальный:

SELECT c.* 
    FROM companies AS c 
    JOIN users AS u USING(companyid) 
    JOIN jobs AS j USING(userid) 
    JOIN useraccounts AS us USING(userid) 
WHERE j.jobid = 123

То, что я думаю, вероятно, предлагает:

SELECT c.* 
    FROM companies AS c 
    JOIN users AS u on u.companyid = c.companyid
    JOIN jobs AS j on j.userid = u.userid
    JOIN useraccounts AS us on us.userid = u.userid 
WHERE j.jobid = 123

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

Как бы это выглядело, если бы все объединилось в компанию:

SELECT c.* 
    FROM companies AS c 
    JOIN users AS u on u.companyid = c.companyid
    JOIN jobs AS j on j.userid = c.userid
    JOIN useraccounts AS us on us.userid = c.userid
WHERE j.jobid = 123

Это на самом деле не имеет логического смысла ... если только у каждого пользователя нет своей компании.

4.) Волшебство sql заключается в том, что вы можете отображать только определенные столбцы, но все они предназначены для сортировки и фильтрации ...

если вы вернулись

SELECT c.*, j.jobid....  

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

0 голосов
/ 23 октября 2008

Я не уверен насчет части ON против USING (хотя на этом сайте написано, что они одинаковы)

Что касается вопроса заказа, то он полностью зависит от реализации (и, возможно, запроса). MYSQL, скорее всего, выбирает ордер при компиляции запроса. Если вы хотите применить конкретный порядок, вам нужно «вложить» ваши запросы:

SELECT c.*
FROM companies AS c 
    JOIN (SELECT * FROM users AS u 
        JOIN (SELECT * FROM  jobs AS j USING(userid) 
              JOIN useraccounts AS us USING(userid) 
              WHERE j.jobid = 123)
    )

как для части 4: предложение where ограничивает, какие строки из таблицы заданий могут быть присоединены. Так что если есть строки, которые будут объединены из-за совпадающих идентификаторов пользователей, но не имеют правильного идентификатора задания, они будут опущены.

0 голосов
/ 23 октября 2008

СМ. http://dev.mysql.com/doc/refman/5.0/en/join.html

И начните читать здесь:


Присоединиться Обработка изменений в MySQL 5.0.12

Начиная с MySQL 5.0.12, естественные объединения и объединения с использованием USING, включая варианты внешнего соединения, обрабатываются в соответствии со стандартом SQL: 2003. Цель состояла в том, чтобы привести синтаксис и семантику MySQL в соответствие с NATURAL JOIN и JOIN ... USING в соответствии с SQL: 2003. Однако эти изменения в обработке объединения могут привести к различным выходным столбцам для некоторых объединений. Кроме того, некоторые запросы, которые, по-видимому, работают правильно в старых версиях, должны быть переписаны для соответствия стандарту.

Эти изменения имеют пять основных аспектов:

  • Способ, которым MySQL определяет столбцы результатов операций соединения NATURAL или USING (и, следовательно, результат всего предложения FROM).

  • Расширение SELECT * и SELECT tbl_name. * В список выбранных столбцов.

  • Разрешение имен столбцов в соединениях NATURAL или USING.

  • Преобразование соединений NATURAL или USING в JOIN ... ON.

  • Разрешение имен столбцов в состоянии ON для JOIN ... ON.

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