SQL Server CTE, отнесенный в сам, присоединяется медленный

Я записал табличный UDF, который начинает CTE возвращать подмножество строк от большой таблицы. Существуют, несколько участвуют в CTE. Несколько внутренние и один оставленный соединяют с другими таблицами, которые не содержат много строк. CTE имеет, где пункт, который возвращает строки в диапазоне дат для возврата только необходимых строк.

Я затем ссылаюсь на этот CTE в 4 сам оставленный соединения для создания промежуточных итогов с помощью другого criterias.

Запрос довольно сложен, но здесь является упрощенной псевдоверсией его

WITH DataCTE as
(
     SELECT [columns] FROM table
                      INNER JOIN table2
                      ON [...]

                      INNER JOIN table3
                      ON [...]

                      LEFT JOIN table3
                      ON [...]
)
SELECT [aggregates_columns of each subset] FROM DataCTE Main
LEFT JOIN DataCTE BananasSubset
               ON [...] 
             AND Product = 'Bananas'
             AND Quality = 100
LEFT JOIN DataCTE DamagedBananasSubset
               ON [...]
             AND Product = 'Bananas'
             AND Quality < 20
LEFT JOIN DataCTE MangosSubset
               ON [...]
GROUP BY [

У меня есть чувство, что SQL Server запутывается и называет CTE для каждого сам соединение, которое кажется подтвержденным путем рассмотрения плана выполнения, хотя я признаюсь в том, чтобы не быть экспертом при чтении их.

Я предположил бы, что SQL Server достаточно умен, чтобы только выполнить поиск данных от CTE только однажды, вместо того, чтобы несколько раз делать это.

Я попробовал тот же подход, а скорее, чем использование CTE для получения подмножества данных, я использовал тот же запрос Select в качестве в CTE, но заставил его произвести к временной таблице вместо этого.

Версия, отсылающая версию CTE, занимает 40 секунд. Версия, отсылающая временную таблицу, берет между 1 и 2 секундами.

Почему SQL Server не достаточно умен для хранения результатов CTE в памяти?

Мне нравится CTEs, особенно в этом случае, поскольку мой UDF является табличным, таким образом, он позволил мне сохранять все в отдельном операторе.

Для использования временной таблицы я должен был бы записать, что составная таблица оценила UDF, который я нахожу немного менее изящным решением.

У некоторых из Вас был этот вид проблем производительности с CTE, и если так, как Вы сортировали их?

Спасибо,

Kharlos

8
задан Kharlos Dominguez 16 June 2010 в 15:39
поделиться

1 ответ

Я считаю, что результаты CTE извлекаются каждый раз. При использовании временной таблицы результаты сохраняются до тех пор, пока она не будет удалена. Казалось бы, это объясняет прирост производительности, который вы наблюдали при переключении на временную таблицу.

Еще одним преимуществом является то, что вы можете создавать индексы для временной таблицы, чего нельзя сделать с cte. Не уверен, что в вашей ситуации будет польза, но это полезно знать.

Ссылки по теме:

Цитата из последней ссылки:

Основной запрос CTE будет вызывается каждый раз, когда он упоминается в непосредственно следующий запрос.

Я бы посоветовал использовать временную таблицу. К сожалению, элегантность - не всегда лучшее решение.

ОБНОВЛЕНИЕ:

Хммм, это усложняет задачу. Мне трудно сказать, не глядя на все ваше окружение.

Некоторые мысли:

  • Можно ли использовать хранимую процедуру вместо UDF (вместо этого, а не изнутри)?
  • Это может быть невозможно, но если вы можете удалить левое соединение из своего CTE, вы можете переместить его в индексированное представление. Если вы сможете это сделать, вы можете увидеть прирост производительности даже по сравнению с временной таблицей.
6
ответ дан 5 December 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: