Описывает ли порядок таблиц, упомянутых в предложении ON для дела JOIN?
Имеет ли значение, каким образом я заказываю критерии в предложении ON для JOIN?
select a.Name, b.Status from a
inner join b
on a.StatusID = b.ID
против
select a.Name, b.Status from a
inner join b
on b.ID = a.StatusID
Есть ли влияние на производительность? Что делать, если у меня было несколько критериев?
Является ли один заказ более удобным, чем другой?
Ответы
Ответ 1
JOIN
порядок может быть принудительно, поместив таблицы в правильном порядке в предложение FROM
:
-
MySQL
имеет специальное предложение, называемое STRAIGHT_JOIN
, которое делает вопрос порядка.
Это будет использовать индекс на b.id
:
SELECT a.Name, b.Status
FROM a
STRAIGHT_JOIN
b
ON b.ID = a.StatusID
И это будет использовать индекс на a.StatusID
:
SELECT a.Name, b.Status
FROM b
STRAIGHT_JOIN
a
ON b.ID = a.StatusID
-
Oracle
имеет специальный подсказку ORDERED
для обеспечения порядка JOIN
:
Это будет использовать индекс на b.id
или построить хеш-таблицу на b
:
SELECT /*+ ORDERED */
*
FROM a
JOIN b
ON b.ID = a.StatusID
И это будет использовать индекс на a.StatusID
или построить хеш-таблицу на a
:
SELECT /*+ ORDERED */
*
FROM b
JOIN a
ON b.ID = a.StatusID
-
SQL Server
имеет подсказку, называемую FORCE ORDER
, чтобы сделать то же самое:
Это будет использовать индекс на b.id
или построить хеш-таблицу на b
:
SELECT *
FROM a
JOIN b
ON b.ID = a.StatusID
OPTION (FORCE ORDER)
И это будет использовать индекс на a.StatusID
или построить хеш-таблицу на a
:
SELECT *
FROM b
JOIN a
ON b.ID = a.StatusID
OPTION (FORCE ORDER)
подсказки оптимизатора (не нужны)
Рекомендации оптимизатора используются для решения проблем в оптимизаторе. Мы бы предпочли сообщить и зафиксировать проблемы.
Что касается порядка в сравнении, это не имеет значения ни в одном RDBMS
, AFAIK.
Хотя я лично всегда стараюсь оценить, какой столбец будет искать, и поместить этот столбец влево (чтобы он выглядел как lvalue
).
Подробнее см. этот ответ.
Ответ 2
Нет, это не так.
То, что я делаю (для читаемости), является вашим вторым примером.
Ответ 3
Нет. База данных должна определять лучший план выполнения на основе всех критериев, а не создавать его, последовательно просматривая каждый элемент. Вы можете подтвердить это, запросив план выполнения для обоих запросов, вы увидите, что они одинаковы (вы обнаружите, что даже очень разные запросы, если они в конечном итоге указывают одну и ту же логику, часто скомпилируются в один и тот же план выполнения).
Ответ 4
Нет, нет. В конце дня вы действительно просто оцениваете, является ли a = b.
И поскольку симметричное свойство равенства гласит:
- Для любых величин a и b, если a = b, то b = a.
поэтому, если вы проверяете наличие (12)*=12
или 12=(12)*
, то логически не будет различий.
Если значения равны, присоединитесь, если нет, не делайте этого. И укажите ли вы его как в первом примере, либо во втором, не имеет значения.
Ответ 5
Прочтите это
SqlServer содержит оптимизацию для ситуаций, гораздо более сложных, чем это.
Если у вас есть несколько критериев, материал обычно ленится (но мне нужно сделать немного исследований по крайним случаям, если они есть.)
Для удобства чтения я обычно предпочитаю
SELECT Name, Status FROM a
JOIN b
ON a.StatusID = b.ID
Я думаю, что имеет смысл ссылаться на переменную в том же порядке, в каком они были объявлены, но на самом деле это личный вкус.
Ответ 6
Единственная причина, по которой я не буду использовать ваш второй пример:
select a.Name, b.Status
from a
inner join b
on b.ID = a.StatusID
Ваш пользователь, скорее всего, вернется и скажет: "Могу ли я увидеть все имя a.name, даже если у них нет записей о состоянии?" а не "Могу ли я увидеть все b.status, даже если у них нет записи имен?", поэтому просто для планирования вперед в этом примере я бы использовал On a.StatusID = b.ID
в ожидании LEFT Outer Join. Это предполагает, что у вас может быть таблица "a" без "b".
Коррекция: он не изменит результат.
Это, вероятно, спорный момент, поскольку пользователи никогда не хотят менять свои требования.
Ответ 7
Как многие говорили: порядок не влияет на результат или производительность.
Я хочу отметить, что LINQ to SQL допускает только первый случай!
Например, следующий пример хорошо работает,...
var result = from a in db.a
join b in db.b on a.StatusID equals b.ID
select new { Name = a.Name, Status = b.Status }
... в то время как это вызовет ошибки в Visual Studio:
var result = from a in db.a
join b in db.b on b.ID equals a.StatusID
select new { Name = a.Name, Status = b.Status }
Что вызывает эти ошибки компилятора:
- CS1937: имя "имя" не находится в области действия в левой части "равно". Рассмотрим замену выражений по обе стороны от "равно".
- CS1938: имя "имя" не находится в области действия с правой стороны от "равно". Рассмотрим замену выражений по обе стороны от "равно".
Хотя это не относится к стандартному SQL-кодированию, это может быть точкой рассмотрения, когда вы привыкаете к одному из них.
Ответ 8
нет, не имеет значения. но вот пример, который поможет сделать ваши запросы более читабельными (по крайней мере для меня).
select a.*, b.*
from tableA a
inner join tableB b
on a.name=b.name
and a.type=b.type
каждая таблица ссылается на отдельную строку, и каждый критерий соединения находится на отдельной строке. tabbing помогает сохранить то, что принадлежит тому, что прямо.
Еще одна вещь, которую мне нравится делать, - это сделать мои критерии в моих операторах в том же порядке, что и таблица. поэтому, если a является первым, а затем b, a будет с левой стороны и b справа.