SQL Server Multi-Statement UDF - способ временного хранения данных - PullRequest
1 голос
/ 16 июня 2010

У меня довольно сложный запрос с несколькими самостоятельными объединениями, который работает на довольно большой таблице.Чтобы этот запрос выполнялся быстрее, мне нужно работать только с подмножеством данных.Упомянутое подмножество данных может содержать от 12 000 до 120 000 строк в зависимости от переданных параметров.

Более подробную информацию можно найти здесь: SQL Server CTE, относящийся к самостоятельным соединениям, медленно

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

Альтернатива, с использованием временных таблиц, работала намного быстрее (при тестировании запроса в отдельном окне вне тела UDF).Однако когда я попытался реализовать это в пользовательской функции с несколькими операторами, SQL Server жестко напомнил мне, что пользовательские функции с несколькими операторами по какой-то причине не поддерживают временные таблицы ...

Пользовательские функции допускают использование табличных переменных.Я попытался это сделать, но производительность абсолютно ужасна, поскольку для выполнения моего запроса требуется 1m40, тогда как версия CTE only заняла 40 секунд.Я полагаю, что переменные таблицы работают медленно по причинам, перечисленным в этой теме: Низкая производительность табличных переменных при вставке в хранимой процедуре SQL Server

Версия временной таблицы занимает около 1 секунды, но я не могусделать это функцией из-за ограничений SQL Server, и у меня есть для возврата таблицы вызывающей стороне.

Учитывая, что переменные CTE и таблицы слишком медленные и временныетаблицы отклоняются в UDF. Какие есть варианты для быстрого выполнения UDF?

Заранее большое спасибо.

Ответы [ 3 ]

3 голосов
/ 16 июня 2010

Во многих таких случаях все, что нам нужно сделать, это объявить первичные ключи для этих табличных переменных, и это снова быстро.

0 голосов
/ 16 июня 2010

Один хитрый обходной путь, который я использовал, включает в себя такой код (следующий код psuedo):

CREATE TEMP TABLE #foo

EXECUTE MyStoredProcedure

SELECT *
 from #foo

GO

--  Stored procedure definition
CREATE PROCEDURE MyStoredProcedure
AS

INSERT #foo values (whatever)

RETURN
GO

Короче говоря, хранимая процедура ссылается и использует временную таблицу, созданную вызывающей процедурой (или подпрограммой). Это будет работать, но для других может быть затруднительно следить за тем, что происходит, если вы не задокументируете это четко, и вы получите перекомпиляцию, статистические пересмотры и другие странности, которые могут потреблять нежелательные тактовые циклы.

...