29 авг. 2012 г., 18:01 отLuke GirvinFlySwat

SQLServer: Почему следует избегать пользовательских функций с табличными значениями?

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

Хотя я не знаю, что именно делает их медленными, я буду догадываться, что они есть, но, видя, что я не использую этот UDF в соединении, а вместо этого возвращает табличную переменную, я думаю, что это не будет будь таким плохим.

Так что я думаю, вопрос в том, стоит ли мне избегать UDF любой ценой? Кто-нибудь может указать на конкретные доказательства того, что они медленнее?

Ответы на вопрос(4)

04 июл. 2009 г., 01:51 от

что результаты (таблицы) udf не будут объединены ни с чем, тогда не будет никакого влияния на производительность.

Чтобы попытаться объяснить немного о том, почему UDF могут восприниматься как медленные (на самом деле просто используются неправильно), рассмотрим следующий пример;

У нас есть таблица A и таблица B. Скажем, у нас было соединение как

ВЫБРАТЬ     A.col1,     A.col2,     B.ColWhatever ОТ          ПРИСОЕДИНЯЙТЕСЬ К B A. A.id = b.fk_aid ГДЕ     B.someCol = @ param1 И A.anotherCol = @ param2

В этом случае SQL Server будет делать все возможное, чтобы возвращать результаты наиболее эффективным способом, который он знает как. Основным фактором в этом является сокращение чтения с диска. Таким образом, он будет использовать условия в JOIN и предложение where для оценки (возможно, с индексом) количества строк, которые нужно вернуть.

Теперь, скажем, мы извлекаем некоторую часть условий, используемых для ограничения объема данных, возвращаемых в UDF. Теперь оптимизатор запросов больше не может извлекать минимальное количество строк с диска, он может работать только с условиями, которые он предоставляет. В двух словах - таблица udf всегда оценивается, и данные возвращаются перед возвратом в основной sproc, поэтому, если в исходном объединении были какие-то другие критерии, которые могли бы вызвать меньше операций чтения с диска - это будет применяться только к данным будучи втянутым в спрок.

Допустим, мы создали UDF, чтобы выбрать строки из таблицы B, которые соответствуют предложению where. Если в таблице B 100 тыс. Строк, и 50% из них соответствуют критериям предложения where, то все эти строки будут возвращены в sproc для сравнения с таблицей A. Теперь, если только 10% из них имеют совпадения в таблице A, сейчас мы говорим только о 5% таблицы B, с которой мы хотим работать, но мы уже откатили 50%, большинство из которых мы не хотим!

Если это выглядит как полное извинение - пожалуйста, дайте мне знать!

04 июл. 2009 г., 02:14 отA-K

встроенные пользовательские функции на самом деле являются макросами, поэтому они очень быстрые: Несколько статей:

Повторно используйте ваш код с табличными UDF

Многие вложенные встроенные UDF работают очень быстро

Дополнительные ссылки на медлительность скалярных UDF:

Шаблоны производительности SQL Server UDF с параметрами datetime

Не все UDF плохо влияют на производительность

04 июл. 2009 г., 01:18 отCodeMonkey1313
04 июл. 2009 г., 01:53 отjn29098

если вы используете скалярный udf в предложении select запроса, операторы внутри udf будут выполняться один раз для каждой строки, возвращаемой из запроса. Было бы лучше выполнить соединение с табличным udf или найти какой-либо способ выполнить логику в вашем udf, используя соединение в вашем основном операторе SQL.

ВАШ ОТВЕТ НА ВОПРОС