В чем разница между общим выражением таблицы (CTE) и временной таблицей? И когда я должен использовать один над другим?
КТР
WITH cte (Column1, Column2, Column3)
AS
(
SELECT Column1, Column2, Column3
FROM SomeTable
)
SELECT * FROM cte
Temp Table
SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable
SELECT * FROM #tmpTable
sql-server
cte
Рейчел
источник
источник
Ответы:
Это довольно широкий вопрос, но я дам вам общий ответ, как только смогу.
, CTE ...
VIEW
s#Temp Tables ...
Что касается того, когда использовать каждый, у них очень разные варианты использования. Если у вас будет очень большой набор результатов или вам нужно будет ссылаться на него более одного раза, поместите его в
#temp
таблицу. Если он должен быть рекурсивным, одноразовым или просто для упрощения чего-либо логически,CTE
предпочтительным является a .Кроме того ,
CTE
не должно никогда быть использовано для выполнения . Вы почти никогда не будете ускорять процесс с помощью CTE, потому что, опять же, это просто одноразовое представление. Вы можете делать с ними некоторые полезные вещи, но ускорение запроса на самом деле не является одним из них.источник
РЕДАКТИРОВАТЬ:
Пожалуйста, смотрите комментарии Мартина ниже:
Оригинальный ответ
КТР
Узнайте больше на MSDN
CTE создает таблицу, используемую в памяти, но она действительна только для конкретного запроса, следующего за ним. При использовании рекурсии это может быть эффективной структурой.
Вы также можете рассмотреть возможность использования табличной переменной. Это используется как временная таблица и может использоваться несколько раз без необходимости повторной материализации для каждого соединения. Кроме того, если вам нужно сохранить несколько записей сейчас, добавить еще несколько записей после следующего выбора, добавить еще несколько записей после другой операции, а затем вернуть только те несколько записей, тогда это может быть удобной структурой, поскольку не нужно бросать после казни. В основном просто синтаксический сахар. Однако, если вы сохраняете низкое количество строк, оно никогда не материализуется на диск. См. В чем разница между временной таблицей и табличной переменной в SQL Server? Больше подробностей.
Temp Table
Узнайте больше на MSDN - прокрутите около 40% пути
Временная таблица - это буквально таблица, созданная на диске, только в определенной базе данных, которую, как все знают, можно удалить. Хороший разработчик несет ответственность за уничтожение этих таблиц, когда они больше не нужны, но администратор базы данных также может их стереть.
Временные таблицы бывают двух видов: локальные и глобальные. В терминах MS Sql Server вы используете
#tableName
обозначение для локального и##tableName
обозначение для глобального (обратите внимание на использование одинарного или двойного # в качестве идентифицирующей характеристики).Обратите внимание, что с временными таблицами, в отличие от табличных переменных или CTE, вы можете применять индексы и т. П., Поскольку они являются законными таблицами в обычном смысле этого слова.
Обычно я использовал бы временные таблицы для более длинных или больших запросов, а также CTE или переменные таблиц, если бы у меня уже был небольшой набор данных, и я хотел просто быстро написать небольшой код для чего-то небольшого. Опыт и советы других указывают на то, что вы должны использовать CTE, в которых у вас есть небольшое количество строк, возвращаемых из него. Если у вас большое число, вы, вероятно, выиграете от возможности индексировать временную таблицу.
источник
SELECT Column1, Column2, Column3 FROM SomeTable
WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X
, а также проверяют планы выполнения. Хотя иногда можно взломать план, чтобы получить катушку. Есть пункт подключения, запрашивающий подсказку для этого.Принял ответ здесь говорит «КТР никогда не должен быть использован для выполнения» , - но это может ввести в заблуждение. В контексте CTE по сравнению с временными таблицами, я только что закончил удаление полосы мусора из набора хранимых процедур, потому что некоторые глупцы, должно быть, думали, что использование временных таблиц было незначительным или отсутствовало. Я вложил все это в CTE, за исключением тех, которые на законных основаниях собирались повторно использовать на протяжении всего процесса. Я получил около 20% производительности по всем показателям. Затем я приступил к удалению всех курсоров, которые пытались реализовать рекурсивную обработку. Именно здесь я увидел наибольшую выгоду. В итоге я сократил время отклика в десять раз.
CTE и временные таблицы имеют очень разные варианты использования. Я просто хочу подчеркнуть, что, хотя это и не панацея, понимание и правильное использование CTE могут привести к некоторым по-настоящему звездным улучшениям как качества / удобства сопровождения, так и скорости. Так как я справился с ними, я вижу временные таблицы и курсоры как большое зло обработки SQL. Теперь я могу прекрасно справляться с табличными переменными и CTE практически для всего. Мой код чище и быстрее.
источник
CTE может вызываться повторно в запросе и вычисляется каждый раз, когда на него ссылаются - этот процесс может быть рекурсивным. Если на него ссылаются только один раз, то он ведет себя во многом как подзапрос, хотя параметры CTE могут быть параметризованы.
Временная таблица физически сохраняется и может быть проиндексирована. На практике оптимизатор запросов может также сохранять промежуточные результаты соединения или подзапроса за кулисами, например, в операциях спула, поэтому не совсем верно, что результаты CTE никогда не сохраняются на диске.
Переменные таблицы IIRC (с другой стороны) всегда являются структурами в памяти.
источник
Временная таблица - это реальный объект в базе данных tempdb, но cte - это всего лишь оболочка для сложного запроса, упрощающая синтаксис организации рекурсии за один шаг.
источник
Основной причиной использования CTE является доступ к функциям окна, таким как
row_number()
и другие.Это означает, что вы можете делать такие вещи, как получить первый или последний ряд для группы ОЧЕНЬ ОЧЕНЬ быстро и эффективно - более эффективно, чем другие средства в большинстве практических случаев .
Вы можете выполнить запрос, аналогичный приведенному выше, используя коррелированный подзапрос или подзапрос, но CTE будет быстрее почти во всех сценариях.
Кроме того, CTE могут действительно помочь упростить ваш код. Это может привести к повышению производительности, поскольку вы лучше понимаете запрос и можете использовать больше бизнес-логики, чтобы оптимизатор был более избирательным.
Кроме того, CTE могут повысить производительность, если вы понимаете свою бизнес-логику и знаете, какие части запроса должны выполняться первыми - как правило, сначала ставьте самые избирательные запросы, которые приводят к наборам результатов, которые могут использовать индекс при следующем соединении, и добавляйте
option(force order)
запрос. намекНаконец, CTE не используют базу данных tempdb по умолчанию, поэтому вы можете уменьшить количество конфликтов в этом узком месте за счет их использования.
Временные таблицы следует использовать, если вам нужно многократно запрашивать данные, или, в качестве альтернативы, если вы измеряете свои запросы и обнаруживаете это, вставляя во временную таблицу, а затем добавляя индекс, повышающий вашу производительность.
источник
Кажется, здесь есть немного негатива по отношению к CTE.
Мое понимание CTE - то, что это в основном вид ad-hoc. SQL является декларативным и основанным на множестве языком. CTE - отличный способ объявить сет! Неспособность индексировать CTE - это действительно хорошая вещь, потому что вам это не нужно! Это действительно своего рода синтаксический сахар, облегчающий чтение / запись запроса. Любой приличный оптимизатор разработает лучший план доступа, используя индексы на базовых таблицах. Это означает, что вы можете эффективно ускорить ваш запрос CTE, следуя советам по индексам для базовых таблиц.
Кроме того, то, что вы определили набор как CTE, не означает, что все строки в наборе должны быть обработаны. В зависимости от запроса оптимизатор может обработать «достаточно» строк, чтобы удовлетворить запрос. Может быть, вам нужны только первые 20 или около того для вашего экрана. Если вы построили временную таблицу, то вам действительно нужно читать / записывать все эти строки!
Исходя из этого, я бы сказал, что CTE - отличная особенность SQL и может использоваться везде, где они облегчают чтение запроса. Я бы подумал только о временной таблице для пакетного процесса, который действительно должен обрабатывать каждую запись. Даже тогда, на самом деле, это не очень рекомендуется, потому что для временной таблицы базе данных гораздо сложнее помочь вам с кэшированием и индексами. Возможно, лучше иметь постоянную таблицу с полем PK, уникальным для вашей транзакции.
Я должен признать, что мой опыт в основном связан с DB2, поэтому я предполагаю, что CTE работает одинаково в обоих продуктах. Я с радостью исправлюсь, если CTE каким-то образом уступает SQL-серверу. ;)
источник