Почему запрос выполняется намного быстрее, когда я (вручную) кэширует результаты табличной функции во временной таблице?

Почему версия Query Version 2 намного быстрее?

Я подозреваю, что БД-движок многократно вызывает функцию "GetUsageStatistic" в таблице значений, так что есть способ сообщить движку, что "GetUsageStatistic" является детерминированным и его следует вызывать только один раз?

Запрос версии 1

--Takes ~10 minutes
select *
from RosterLevel r
left join GetUsageStatistics( @mindate, @maxdate ) usage on r.UserID = usage.UserID;

Версия запроса 2

--Takes ~10 seconds
select * into #usage from  GetUsageStatistics( @mindate, @maxdate );
select *
from RosterLevel r
left join #usage on r.UserID = #usage.UserID;

Ответ 1

Как упоминалось в комментариях, лучшим ответом является анализ любого плана выполнения. Если вы не согласны с этим, ваша интуиция, вероятно, правильная, но, помимо того, что все попытки кэширования SQL Server автоматически предпринимаются, в моей голове не так много подсказок подсказок, которые вы можете предоставить, чтобы указать, что функция детерминирована, но вы можете попробовать несколько вещей, упомянутых в странице подсказок MSDN. Мои первые тесты, вероятно, будут нарисованы на Таблица подсказок.

Ответ 2

Если вы используете функцию в первом примере, ее вызывают много раз - один раз для каждой записи в таблице RosterLevel. Он возвращает каждую потенциальную таблицу в зависимости от поля объединения.

Если вы используете функцию во втором примере, она вызывается только один раз. Оттуда переменная таблицы находится в памяти, и вам не нужно делать чтение снова и снова.