Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Вызов UDF сильно тормозит / 12 сообщений из 12, страница 1 из 1
01.08.2019, 20:02
    #39844298
Alexey30
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Добрый день.
Есть простейшая функция для нахождения минимального значения из трех:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE FUNCTION [dbo].[InlineMin3Money](@val1 money, @val2 money, @val3 money)
RETURNS money
WITH SCHEMABINDING
AS
BEGIN
	
RETURN	Case When @Val1 < @Val2 And @Val1 < @Val3 Then @Val1
            When @Val2 < @Val1 And @Val2 < @Val3 Then @Val2 
            Else @Val3
            End

END



Возьмем тестовый скрипт:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SET NOCOUNT ON 
SET STATISTICS TIME OFF

DECLARE @a TABLE(price1 MONEY, price2 MONEY, price3 MONEY)
DECLARE @i INT = 0

WHILE @i < 5000
BEGIN
	INSERT @a
		VALUES(1,2,3)

	SET  @i = @i + 1
END

SET STATISTICS TIME on

SELECT 
    dbo.InlineMin3Money(price1,price2,price3)
FROM @a



На нашем довольно шустром сервере он выполняется в среднем в район 50мс.

Если же заменяем вызов функции на выражение прямо в строке, то время выполнения снижается до 2-3мс.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SET NOCOUNT ON 
SET STATISTICS TIME OFF

DECLARE @a TABLE(price1 MONEY, price2 MONEY, price3 MONEY)
DECLARE @i INT = 0

WHILE @i < 5000
BEGIN
	INSERT @a
		VALUES(1,2,3)

	SET  @i = @i + 1
END

SET STATISTICS TIME on

SELECT 
    	Case When price1 < price2 And price1 < price3 Then price1
				When price2 < price1 And price2 < price3 Then price2 
				Else price3
				END
FROM @a



То есть всё тоже самое, только без вызова функции.
Подскажите, пожалуйста, как сделать её вызов более быстрым? В реальном запросе выражения более громоздкие, поэтому их пихать напрямую без функции неудобно.
Спасибо.
...
Рейтинг: 0 / 0
01.08.2019, 20:11
    #39844299
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Alexey30Подскажите, пожалуйста, как сделать её вызов более быстрым?Сделать функцию инлайновой
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
CREATE FUNCTION [dbo].[InlineMin3Money](@val1 money, @val2 money, @val3 money)
RETURNS table
AS
return	
 select	Case When @Val1 < @Val2 And @Val1 < @Val3 Then @Val1
            When @Val2 < @Val1 And @Val2 < @Val3 Then @Val2 
            Else @Val3
        End as min_val
go

DECLARE @a TABLE(price1 MONEY, price2 MONEY, price3 MONEY)
DECLARE @i INT = 0

WHILE @i < 5000
BEGIN
	INSERT @a
		VALUES(1,2,3)

	SET  @i = @i + 1
END

SET STATISTICS TIME on

SELECT 
 *
FROM @a a cross apply
dbo.InlineMin3Money(price1, price2, price3) b



Ну или дождаться 2019-го сервера.
...
Рейтинг: 0 / 0
01.08.2019, 20:16
    #39844302
Alexey30
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Спасибо за ответ.
Cross Apply в примере использовать удобно, а в реальном запросе особо не вариант.
Неужели нет никакого более "красивого" метода?
Microsoft SQL Server 2016 (SP2-GDR)
...
Рейтинг: 0 / 0
01.08.2019, 20:32
    #39844309
Гавриленко Сергей Алексеевич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Установить сервер, в котором есть инлайновые скалярки.
...
Рейтинг: 0 / 0
01.08.2019, 20:37
    #39844314
Alexey30
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Гавриленко Сергей Алексеевич, печально.
CLR можно не пробовать?
...
Рейтинг: 0 / 0
01.08.2019, 20:59
    #39844322
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Alexey30,

как раз подходящий случай для CLR функции.
...
Рейтинг: 0 / 0
01.08.2019, 21:17
    #39844324
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Alexey30Cross Apply в примере использовать удобно, а в реальном запросе особо не вариант.А почему?
...
Рейтинг: 0 / 0
01.08.2019, 22:56
    #39844340
Alexey30
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
invm, запрос читается сложнее, на мой взгляд. Странно запихивать во FROM то, что должно быть в SELECT.
Однако действительно работает довольно шустро, изменил только тело функции на такое:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
ALTER FUNCTION [dbo].[InlineMin3MoneyInline](@val1 money, @val2 money, @val3 money)
RETURNS table
AS
return	
 select	MIN(val) min_val
 FROM (
	VALUES(@val1), (@val2), (@val3)) a(val)
go
...
Рейтинг: 0 / 0
01.08.2019, 22:58
    #39844341
Alexey30
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Alexey30, При этом производительность чуть-чуть хуже, чем в первоначальном варианте функции, но там отсутствовали проверки на NULL.
...
Рейтинг: 0 / 0
01.08.2019, 23:20
    #39844346
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Alexey30,

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

Соответственно, первый вариант не сможет использовать параллельный план выполнения, как минимум.
...
Рейтинг: 0 / 0
02.08.2019, 00:47
    #39844358
vikkiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Alexey30..Cross Apply в примере использовать удобно, а в реальном запросе особо не вариант.
Неужели нет никакого более "красивого" метода?..насколько помню cross apply будет для каждой строки, одна за одной, по очереди, впрочем как и функция на строку
т.е. по любому последовательное выполнение без паралельности
единственная паралельность как указали выше - в пределах одной строки по значениям под-таблицы,
т.е. как-бы лучше - но и не сильно

для полной паралельности - можно попробовать табличную CLR,
и там уже внутри выстраивать многопоточный алгоритм
...
Рейтинг: 0 / 0
02.08.2019, 09:53
    #39844447
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вызов UDF сильно тормозит
Alexey30Спасибо за ответ.
Cross Apply в примере использовать удобно, а в реальном запросе особо не вариант.
Неужели нет никакого более "красивого" метода?
Microsoft SQL Server 2016 (SP2-GDR)

Функции - зло ;-)

Сделайте запрос с раскрученным запросом в процедуре
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Вызов UDF сильно тормозит / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]