2010-02-14 1 views
19

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

В какой последовательности будут запросы и подзапросы, выполняемым SQL двигатель?

ответы были

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

Я выбрал последний ответ (просто предположив, что он является самым надежным w.r.t. другие). В настоящее время интересно:

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

спасибо.

ответ

12

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

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

Это означает, что фиксированного заказа нет. Но это не совсем «на лету»

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

0

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

+0

, а с другой стороны - подзапросы часто зависят от припаркованного запроса (коррелированные подзапросы). ps: привет от phpclub ;-) – zerkms

0

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

20

Я думаю, что ответ 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. В этом случае он может по-прежнему использовать подход, используемый для некоррелированного подзапроса, если он может предположить, что стоимость выполнения подзапроса один раз будет дешевле, чем для каждой строки.

+0

Thak вы за ответ, любые идеи о том, где читать, лучший источник? – Igor

+2

Если во втором примере вместо 'from t2' мы имели' из t2, t1', то основной запрос и подзапрос не были скоррелированы. я прав ? – alex

+0

Это правильно. Тогда выражение t1.type в WHERE подзапроса будет разрешено к t1 в предложении FROM подзапроса, а не к внешнему запросу. Подзапрос тогда не будет иметь никаких ссылок на внешний запрос и поэтому будет некоррелирован. –

1

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