Встроенные представления позволяют выбирать из подзапроса, как если бы это была другая таблица:
SELECT
*
FROM /* Selecting from a query instead of table */
(
SELECT
c1
FROM
t1
WHERE
c1 > 0
) a
WHERE
a.c1 < 50;
Я видел, что это относится к использованию различных терминов: встроенные представления, предложение WITH, CTE и производные таблицы. Мне кажется, что они отличаются друг от друга синтаксисом для одного и того же производителя.
Это неправильное предположение? Есть ли какие-либо технические различия между ними?
oracle
cte
derived-tables
Кшитиз Шарма
источник
источник
WITH...
). Вы можете переписать каждую производную таблицу как CTE, но, возможно, не наоборот (например, рекурсивный CTE или многократное использование CTE)Ответы:
Есть некоторые важные различия между встроенными представлениями (производными таблицами) и предложением WITH (CTE) в Oracle. Некоторые из них достаточно универсальны, то есть применимы к другим СУБД.
WITH
может быть использован для создания рекурсивных подзапросов, встроенное представление -не (насколько я знаю, то же самое для всех RDBMS, которые поддерживают CTE)WITH
предложении, скорее всего, будет физически выполнен первым; во многих случаях выбор междуWITH
и встроенным представлением заставляет оптимизатор выбирать различные планы выполнения (я полагаю, это зависит от поставщика, возможно, даже от версии).WITH
может быть материализован как временная таблица (я не знаю, если какой-либо другой поставщик, но Oracle поддерживает эту функцию).WITH
можно ссылаться несколько раз, в других подзапросах и в основном запросе (верно для большинства СУБД).источник
LATERAL
не используется.Другие ответы достаточно хорошо охватывают синтаксические различия, поэтому я не буду вдаваться в подробности. Вместо этого этот ответ будет охватывать только производительность в Oracle.
Оптимизатор Oracle может выбрать материализацию результатов CTE во внутреннюю временную таблицу. Для этого используется эвристика вместо оптимизации на основе затрат. Эвристика - это что-то вроде «Материализации CTE, если это не тривиальное выражение и CTE упоминается в запросе более одного раза». Есть несколько запросов, по которым материализация улучшит производительность. Есть несколько запросов, по которым материализация резко снизит производительность. Следующий пример немного надуманный, но хорошо иллюстрирует это:
Сначала создайте таблицу с первичным ключом, который содержит целые числа от 1 до 10000:
Рассмотрим следующий запрос, который использует две производные таблицы:
Мы можем посмотреть на этот запрос и быстро определить, что он не будет возвращать никаких строк. Oracle должен иметь возможность использовать индекс, чтобы определить это. На моей машине запрос почти мгновенно заканчивается следующим планом:
Мне не нравится повторяться, поэтому давайте попробуем тот же запрос с CTE:
Вот план:
Это действительно плохой план. Вместо использования индекса Oracle материализует 10000 X 10000 = 100000000 строк во временную таблицу только для того, чтобы в итоге вернуть 0 строк. Стоимость этого плана составляет около 6 млн., Что намного выше, чем другой запрос. На моем компьютере запрос занял 68 секунд.
Обратите внимание, что запрос мог завершиться неудачно, если в табличном пространстве temp недостаточно памяти или свободного места.
Я могу использовать недокументированную
INLINE
подсказку, чтобы запретить оптимизатору материализовать CTE:Этот запрос может использовать индекс и завершается практически мгновенно. Стоимость запроса такая же, как и раньше, 11. Таким образом, для второго запроса эвристика, используемая Oracle, привела к тому, что он выбрал запрос с оценочной стоимостью 6 М вместо запроса с оценочной стоимостью 11.
источник
Для SQL Server
WITH CTE
указывает временный именованный набор результатов, но требуется только для первогоCTE
. т.е.Но это не подзапрос или коррелированный подзапрос. Есть вещи, которые вы можете сделать с CTE, чего нельзя сделать с подзапросом в SQL Server, например, обновить таблицы, на которые есть ссылки в CTE. Вот пример обновления таблицы с помощью CTE.
Подзапрос будет что-то вроде
Или коррелированный подзапрос - это то, что вы указали в своем OP, если вам нужно было ссылаться / объединять / ограничивать свои результаты на основе a.c1.
Таким образом, они определенно не одно и то же, хотя во многих случаях вы можете использовать один или несколько из этих методов для достижения того же результата. Это просто зависит от того, каков этот конечный результат.
источник
Основное различие между
with
предложением и подзапросом в Oracle состоит в том, что вы можете ссылаться на запрос в предложении несколько раз. Затем вы можете выполнить некоторые оптимизации, например, превратив его во временную таблицу, используяmaterialize
подсказку. Вы также можете выполнять с ним рекурсивные запросы, ссылаясь на себя внутриwith
предложения. Вы не можете сделать это со встроенным представлением.Более подробную информацию можно найти здесь и здесь .
источник
MATERIALIZE
соответственно.INLINE
для противоположности.materialize
подсказки является допустимым вариантом. Иногда мне приходилось указывать это при оптимизации очень сложных запросов, когда я знал, что материализация CTE принесет пользу плану выполнения.Вы должны быть осторожны с CTE в SQL-сервере, а не только с оракулом, в некоторых случаях запросы работают намного хуже при использовании CTE по сравнению с подзапросами, перекрестным применением и т. Д.
Как всегда, важно протестировать любой запрос при различных условиях нагрузки, чтобы определить, какой из них работает лучше всего.
Подобно @scsimon с оракулом, иногда сервер MS SQL не делает то, что вы ожидаете в отношении использования индекса.
Если вы собираетесь использовать одни и те же данные более одного раза, CTE могут быть более полезными, если вы используете их только один раз, часто подзапрос выполняется быстрее в больших наборах данных.
Например, выберите * из (мой подзапрос) присоединиться к чему-то еще ...
источник