Где-то на форуме был вопрос типа
'как правильно и/или что быстрее: WHERE, JOIN, и т.д.'(помнится даже отвечал на него, но теперь оказывается - не совсем правильно)
Недавно передо мной возник этот же вопрос......
Поэкспериментировав, почитав статейки из инет,
хочу поделится своими выводами....
Критика принимается
ЗАДАЧА: хотим получить результат из табл.А, наложив доп.условие на реквизит А,
который 'живет' в табл.Б
и при этом на таблицу Б накладываем еще одно некоторое доп.условие ч/з WHERE
SELECT А.ID
FROM A
{ INNER | LEFT,RIGHT OUTER | FULL } JOIN А.РевизитСсылка = Б.ID
WHERE (.... дополн.фильтр по Б)
ВАРИАНТЫ ЗАПРОСОВ (как результат курения планов + чтения статей из интернет): http://stackoverflow.com/questions/2389204/left-inner-join-vs-left-outer-join-wh... http://www.skillz.ru/dev/php/article-Obyasnenie_SQL_obedinenii_JOIN_INNER_OUTER.... http://bytes.com/topic/sql-server/answers/82859-sql-syntax-inner-outer-join-vs-w... http://ru.wikipedia.org/wiki/Join_(SQL) получил такое:
INNER: 1. сперва сканируется Б (по его фильтру из WHERE) и формируется <Список Б.ID>
2. из А выбираются только те записи, для которых {А.РевизитСсылка = УжеОтобранныеЗаписиБ.ID}
т.е. во втором запросе (при сканировании А)
собственно JOIN-условие
<А.РеквА = Б.РеквБ> как бы превращается в WHERE-условие
<А.РеквА IN (уже отобранные Б.ID)> LEFT OUTER: (запрос INNER) в полном объеме, см.выше
(запрос OUTER А) сканируется А и выбираются те записи, для которых {А.РевизитСсылка = NULL}
(UNION) и его результат присоединяется к первому сканированию
RIGHT OUTER: (запрос INNER) в полном объеме, см.выше
(запрос OUTER Б) сканируется Б и выбираются те записи, что не имеют отношения к А (связь = NULL)
(UNION) результаты 2х сканирований объединяются (UNION)
FULL: (запрос INNER) в полном объеме, см.выше
(запрос OUTER А) сканируется А и выбираются те записи, что не имеют отношения к Б (связь = NULL)
(запрос OUTER Б) сканируется Б и выбираются те записи, что не имеют отношения к А (связь = NULL)
(UNION) все три результата объединяются через UNION
РЕЗУЛЬТАТ: СКОРОСТЬ (при равных условиях WHERE и условиях связи 'А.РевизитСсылка = Б.ID')
INNER - самый быстрый (2 простых последовательных запроса ч/з WHERE: фильтр-2 накладываем на результат фильтра-1)
OUTER - 2е место (все запросы INNER + 1 запрос на NULL + всё объединяем ч/з UNION)
FULL - 3е место (все запросы INNER + 2 запроса на NULL + всё объединяем ч/з UNION)
Причем чем меньше величина отношения количества записей
У = (кол-во отобранных ч/з INNER) / (Всего записей А + Всего записей Б)
тем существенней разница между скоростью INNER (быстрее) vs OUTER|FULL (медленней)
ВЫВОДЫ: 1)
INNER - самый быстрый из всех
JOIN-ов, без надобности OUTER|FULL - не использовать !
2) естественно
WHERE быстрее JOIN, т.к. WHERE это запрос по 1й таблице, а JOIN по 2вум (и более)
P.S. иногда внутреннее соединение пишут так
(и надо понимать что это запрос к 2м таблицам, а не простой WHERE)
SELECT А.ID
FROM A
WHERE (А.РевизитСсылка = Б.ID)
AND (.... дополн.фильтр по Б)
вместо (правильно, хотя первый вариант - не запрещается 8=))
SELECT А.ID
FROM A
[INNER] JOIN А.РевизитСсылка = Б.ID
WHERE (.... дополн.фильтр по Б)