В какой последовательности запросы и подзапросы выполняются механизмом SQL?

Здравствуйте, я сделал тест SQL и засомневался/заинтересовался одним вопросом:

В какой последовательности запросы и подзапросы выполняются механизмом SQL?

ответы были

  1. первичный запрос -> подзапрос -> подзапрос и т. д.
  2. подзапрос -> подзапрос -> основной запрос
  3. весь запрос интерпретируется за один раз
  4. Нет фиксированной последовательности интерпретации, парсер запроса принимает решение на лету

Я выбрал последний ответ (просто предполагая, что он наиболее надежен по сравнению с другими). Теперь любопытство:

где я могу прочитать об этом и вкратце, каков механизм всего этого?

Спасибо.


person Igor    schedule 14.02.2010    source источник


Ответы (5)


Вариант 4 близок.

SQL является декларативным: вы говорите оптимизатору запросов, что вы хотите, и он работает наилучшим образом (с учетом время/"стоимость" и т.д.) способ сделать это. Это может варьироваться для внешне идентичных запросов и таблиц в зависимости от статистики, распределения данных, количества строк, параллелизма и бог знает чего еще.

Это означает, что нет фиксированного порядка. Но это не совсем "на лету"

Я видел, что даже с идентичными серверами, схемой, запросами и данными планы выполнения различаются.

person gbn    schedule 15.02.2010

Я думаю, что ответ 4 правильный. Есть несколько соображений:

тип подзапроса - коррелирован или нет. Рассмотреть возможность:

SELECT *
FROM   t1
WHERE  id IN (
             SELECT id
             FROM   t2
            )

Здесь подзапрос не связан с внешним запросом. Если количество значений в t2.id невелико по сравнению с t1.id, вероятно, наиболее эффективно сначала выполнить подзапрос и сохранить результат в памяти, а затем просмотреть t1 или индекс в t1.id, сопоставив их с кэшированные значения.

Но если запрос:

SELECT *
FROM   t1
WHERE  id IN (
             SELECT id
             FROM   t2
             WHERE  t2.type = t1.type
            )

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

С другой стороны, РСУБД может быть очень умной и понимать, что существует всего несколько возможных значений для t2.type. В этом случае он все еще может использовать подход, используемый для некоррелированного подзапроса, если он может предположить, что стоимость выполнения подзапроса один раз будет дешевле, чем выполнение его для каждой строки.

person Roland Bouman    schedule 14.02.2010
comment
Спасибо за ответ, есть идеи, где почитать, лучший источник? - person Igor; 21.02.2010
comment
Если во втором примере вместо from t2 у нас было from t2,t1, то основной запрос и подзапрос не коррелировались. я прав ? - person alex; 06.06.2016
comment
Это правильно. Выражение t1.type в подзапросе WHERE затем будет преобразовано в t1 в предложении FROM подзапроса, а не во внешнем запросе. Тогда подзапрос больше не будет иметь никаких ссылок на внешний запрос и, следовательно, будет некоррелированным. - person Roland Bouman; 07.06.2016

Механизм SQL пытается оптимизировать порядок выполнения (под)запросов. Часть, решающая это, называется оптимизатором запросов. Оптимизатор запросов знает, сколько строк в каждой таблице, какие таблицы имеют индексы и какие поля. Он использует эту информацию, чтобы решить, какую часть выполнить первой.

person Stephan Eggermont    schedule 14.02.2010

Если вы хотите что-то прочитать по этим темам, получите копию Inside SQL Server 2008: T-SQL Querying. В нем есть две отдельные главы, посвященные логической и физической обработке запросов в SQL Server.

person Frank Kalis    schedule 15.02.2010

Обычно это зависит от вашей СУБД, но... Я думаю, что второй ответ более правдоподобен. Основной запрос обычно не может быть рассчитан без результатов подзапроса.

person Adelf    schedule 14.02.2010
comment
а с другой стороны - подзапросы часто зависят от первичного запроса (коррелированные подзапросы). пс: привет из phpclub ;-) - person zerkms; 15.02.2010