SQL 2019 UDF (определяемая пользователем функция) inlining

 SQL Server 2019 приносит много замечательных новых функций. Многие из них вводятся функциями IQP (Intelligent Query Processing) и значительно повышают производительность запросов.

Некоторое время назад я написал о защите Хэллоуина и о том, как использование SCHEMABINDING в ваших скалярных UDFs может устранить необходимость в уродливых операторах катушки. Подробнее об этом вы можете прочитать здесь: https://sqltechblog.com/2016/10/31/why-halloween-slowed-your-queries/

У Microsoft есть отличный пост об этой новой функции здесь:

https://docs.microsoft.com/en-us/sql/relational-databases/user-defined-functions/scalar-udf-inlining?view=sql-server-ver15

Что касается защиты от Хэллоуина, давайте быстро посмотрим, как она ведет себя в SQL Server 2019.

В качестве быстрого обновления SQL Server 2017 и старше ведут себя так же, не используя SCHEMABINDING.


Обратите внимание, что первый запрос, который использует скалярный UDF, имеет более высокую стоимость из-за катушки.

Если мы запустим это в SQL Server 2019 с использованием режима совместимости 150, что произойдет?


У-у-у! Катушка исчезает без необходимости изменять код, и все, что улучшает производительность без изменений кода, просто потрясающе!

Готы

Как вы, наверное, уже догадались. Встраивание UDF является довольно новым и будет улучшаться с течением времени по мере созревания этой функции. Вы можете заметить, что есть исправления, которые были выпущены для исправления некоторых ошибок, связанных с этой новой функцией. (https://support.microsoft.com/en-us/help/4538581/fix-scalar-udf-inlining-issues-in-sql-server-2019)

На сегодняшний день SQL Server 2019 CU4 является самой последней версией, и, похоже, еще предстоит проделать некоторую работу.

Следующий блок кода, по-видимому, воспроизводит ошибку в текущей последней версии:

Создайте базу данных ReproBug;
GO
USE ReproBug
GO
CREATE TABLE Contact (id int identity(1,1), fname varchar(50), lname varchar (50));
GO

Используйте ReproBug
GO
CREATE OR ALTER PROCEDURE [dbo].[proc_InsertContact]
(
@lastName VARCHAR (100),
@firstName VARCHAR (100)
)
AS
BEGIN
BEGIN TRAN

BEGIN TRY
INSERT INTO Contact (fname, lname) values (@lastName, @firstName);

COMMIT
return 0;
END TRY
BEGIN CATCH
ROLLBACK TRAN
RETURN dbo.fx_GetErrorNumber(Error_number ());
END CATCH
END
GO

Создайте или измените функцию [dbo].[fx_GetErrorNumber] (@errorCode INT = NULL)
возвращает INT как
BEGIN

DECLARE @retValue INT
SET @retValue = 500

IF (@errorCode = 2627)
SET @retValue = 501

RETURN @retValue
END
GO

старпом ДБО.[proc_InsertContact] @lastName= 'Vader’,@firstName=' Darth’;

Msg 596, Уровень 21, состояние 1, строка 43
не может продолжить выполнение, так как сеанс находится в состоянии kill.
Msg 0, Уровень 20, состояние 0, строка 43
произошла серьезная ошибка в текущей команде. Результаты, если таковые имеются, следует отбросить.

Есть ли обходной путь?

Да; вы можете установить режим совместимости на 140 или изменить UDF, чтобы отключить инлайн. Либо измените сам UDFна “ WITH INLINE = OFF“, либо обновите базу данных, чтобы отключить inlining "ALTER DATABASE SCOPED CONFIGURATION SET TSQL_SCALAR_UDF_INLINING = OFF;

Это проблема, которую я наблюдаю, и я буду следить за этим сообщением, когда эта проблема будет решена.

Обновление!

SQL Server 2019 CU5 был выпущен и решает проблему, описанную выше. Спасибо команде за их напряженную работу по постоянному совершенствованию продукта. Вы можете найти SQL Server 2019 CU5 здесь:

https://support.microsoft.com/en-us/help/4552255/cumulative-update-5-for-sql-server-2019