SQL Server 2019: встраивание UDFS в представления

#view #user-defined-functions #sql-server-2019 #inlining

#Вид #определяемые пользователем функции #sql-server-2019 #встраивание

Вопрос:

Я хочу протестировать новую функцию SQL Server 2019 — встраивание функций UDF. Кажется, что это работает хорошо, когда я вызываю функцию простым ВЫБОРОМ. Однако встраивание не выполняется, если функция содержится в представлении.

У меня есть простая скалярная функция:

 CREATE FUNCTION [dbo].[GetEmployeeFullName](@id INT) RETURNS NVARCHAR(100) AS
BEGIN
    DECLARE @ret NVARCHAR(100);

    SELECT @ret = FirstName   ' '   LastName
    FROM Employee
    WHERE EmployeeId = @id;

    RETURN @ret;
END
  

и представление, вызывающее эту функцию:

 CREATE VIEW QEmployee AS
SELECT EmployeeId, dbo.GetEmployeeFullName(EmployeeId) AS FullName, FirstName, LastName, Street, City, ZipCode, EMail, Phone
FROM Employee
  

Если я запускаю только SELECT:

 SELECT EmployeeId, dbo.GetEmployeeFullName(EmployeeId) AS FullName, FirstName, LastName, Street, City, ZipCode, EMail, Phone
FROM Employee
  

функция встроена:

План запроса для ВЫБОРА поверх базовой таблицы

Однако, если я запускаю SELECT поверх представления:

 SELECT * FROM QEmployee
  

встраивание больше не выполняется:

План запроса для ВЫБОРА поверх представления

Я вставил в таблицу 100 тысяч записей. Время обработки запроса в первом случае (когда встраивание завершено) составляет приблизительно 1 секунду, в то время как во втором случае оно превышает 3 секунды. Кто-нибудь может мне объяснить, почему SQL Server не встраивает функцию во втором случае? Я ожидал, что планы запросов в обоих случаях должны быть точно такими же.

Комментарии:

1. Примечание стороны, использование этой скалярной функции кажется избыточным для выполняемого вами теста. Вы уже выбираете из Employee в FROM , поэтому получение скалярной функции для повторного чтения из таблицы кажется «глупым», когда вы могли бы просто поместить FirstName ' ' LastName в SELECT определение вашего VIEW и добиться того же самого.

2. Он также может не выполнять доступ к данным, а просто взять @first, @last и выполнить конкатенацию. В любом случае это должен быть встроенный TVF, а не скалярный. Конечно, это упрощено, чтобы продемонстрировать проблему, а не быть образцовым вариантом использования.

3. Спасибо за комментарии. Я знаю, что использование скалярной функции в этом случае не идеально. Мой вопрос заключается в том, почему планы запросов для двух выборок (одна по таблице и (избыточный) вызов функции, а другая по представлению) различны.