Недавно я рассмотрел функцию SQL-сервера коллеги (в SQL Server 2008
), где он поставил запрос T-SQL
в скалярную пользовательскую функцию. Затем эта функция использовалась в предложении Select запроса.Выполнение запроса T-Sql внутри скалярной пользовательской функции
Я думал, что наличие запроса внутри функции будет иметь ужасную производительность, потому что я предположил, что каждая возвращаемая строка должна будет запускать запрос, даже если этот запрос оптимизирован для запроса по индексу.
Вот пример того, что я говорю о:
create table [PERSON] (
ID int primary key,
FIRSTNAME NVARCHAR(100),
MIDDLENAME NVARCHAR(100) null,
LASTNAME NVARCHAR(100))
GO
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (1, 'BOB', 'M', 'BLUE')
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (2, 'VALERIE', 'J', 'GREEN')
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (3, 'SIMON', 'D', 'RED')
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (4, 'LIONEL', 'W', 'BROWN')
GO
-- Scalar Function with T-SQL
CREATE FUNCTION dbo.fn_FormatNameFromId(
@pnPersonId int
)
Returns nvarchar(300)
AS
Begin
return (Select FIRSTNAME + ' ' + MIDDLENAME + ' ' + LASTNAME
From PERSON
Where ID = @pnPersonId)
End
go
-- Scalar Function without T-SQL
CREATE FUNCTION dbo.fn_FormatNameFromValues(
@psFirstName nvarchar(100),
@psMiddleName nvarchar(100),
@psLastName nvarchar(100)
)
Returns nvarchar(300)
AS
Begin
return (@psFirstName + ' ' + @psMiddleName + ' ' + @psLastName)
End
go
-- T-SQL within function
select dbo.fn_FormatNameFromId(ID)
from PERSON
-- Pass values directly
select dbo.fn_FormatNameFromValues(FIRSTNAME, MIDDLENAME, LASTNAME)
FROM PERSON
При сравнении планов выполнения для обоих этих выбирает, я не мог найти никакой разницы в памяти процессора или выполнения двух функций. Даже при масштабировании теста, чтобы вернуть десятки тысяч строк, разница производительности не изменилась.
Может кто-нибудь объяснить, как и почему fn_FormatNameFromId
не приводит к потере производительности?
Возможно, это из-за кеширования. Вы загружаете все данные из таблицы, а Sql Server загружает все страницы в память. –
«Я думал ... будет иметь ужасное исполнение» - он может иметь худшую производительность, чем эквивалент, но вопрос * first *, о котором вы должны спрашивать, - это текущая эффективность? То есть у вас есть показатели производительности * *, и вы * измерили * текущую производительность? Если это * * работает приемлемо, почему вы тратите время на это? Если это не выполняется приемлемо, у вас уже есть свой ответ. И если вы не ставили цели и не измеряли, как вы знаете, что вы тратите время на то, где должна быть производительность, и ее можно улучшить? –
@Damien_The_Unbeliever, да, спектакль оказался в порядке. Я просто хотел понять, как это работает, чтобы я мог волноваться/не беспокоиться об этом в будущем. Что касается лучшей практики, хотя мы не должны полагаться на оптимизатора. – antman