Я записал табличный 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
Я считаю, что результаты CTE извлекаются каждый раз. При использовании временной таблицы результаты сохраняются до тех пор, пока она не будет удалена. Казалось бы, это объясняет прирост производительности, который вы наблюдали при переключении на временную таблицу.
Еще одним преимуществом является то, что вы можете создавать индексы для временной таблицы, чего нельзя сделать с cte. Не уверен, что в вашей ситуации будет польза, но это полезно знать.
Ссылки по теме:
Цитата из последней ссылки:
Основной запрос CTE будет вызывается каждый раз, когда он упоминается в непосредственно следующий запрос.
Я бы посоветовал использовать временную таблицу. К сожалению, элегантность - не всегда лучшее решение.
ОБНОВЛЕНИЕ:
Хммм, это усложняет задачу. Мне трудно сказать, не глядя на все ваше окружение.
Некоторые мысли:
левое соединение
из своего CTE, вы можете переместить его в индексированное представление. Если вы сможете это сделать, вы можете увидеть прирост производительности даже по сравнению с временной таблицей.