Well, now that you opened a thorny subject :-) I think we need more realistic examples and to refrain from gotcha games. Examples that look too contrived always make me suspicious. So, I rearranged the query just a bit and straight scalar UDF outperformed the query. Dont' believe it - try it - this was on SQL 2k8 on a dev box under 2k8 Server Std.
All we have learned so far is that using computed columns and equivalents in WHERE clauses is bad. That query was using scalar function in WHERE clause while pretending that it's in a select.
SELECT COUNT(*) FROM(
SELECT n as X,n+1 AS ValuePlusOne
FROM dbo.Numbers
) AS t WHERE X>0
Table 'Numbers'. Scan count 1, logical reads 3521, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 234 ms, elapsed time = 228 ms.
SELECT COUNT(*) FROM(
SELECT n as X ,dbo.AddOne(n) AS ValuePlusOne
FROM dbo.Numbers
) AS t WHERE X>0
Table 'Numbers'. Scan count 1, logical reads 3521, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 202 ms, elapsed time = 215 ms.
So, now that we resolved that how about some real info and realistic use cases ?
I'll supply 2 for debate :-) but please remember no contrived gotchas. A TVF and a scalar UDF just calling it to get the value in a convenient way and then use in a query either as a value or in a join - no one's calculating anything. Can someone construct a table or state how pathological data would have to be in order to see perf diff between LCID1 and LCID2 ?
CREATE FUNCTION [PublishingCulture] ( @XLanguage int,
@XLocale int
) RETURNS TABLE
AS
RETURN
(
select TOP 1 * from [Culture] C
where ((C.XLang = @XLanguage and C.XLoc = @XLocale)
or (C.XLang = @XLanguage and C.XLoc = 0)
or (C.XLang = 0 and C.XLoc = @XLocale)
or (C.XLang = 0 and C.XLoc = 0))
)
CREATE FUNCTION [MyLCID1] ( @XLanguage int,
@XLocale int )
RETURNS TABLE
AS
RETURN ( SELECT LCID from dbo.PublishingCulture(@XLanguage, @XLocale) )
CREATE FUNCTION [MyLCID2] ( @XLanguage int,
@XLocale int )
RETURNS int
AS
BEGIN
RETURN ( SELECT LCID from dbo.PublishingCulture(@XLanguage, @XLocale) )
END
select * from
(select Row_number() OVER(order by StartDate) as RN, Message
from [Ticker] as T
join dbo.MyLCID1(@XLanguage, @XLocale) as L on T.LCID = L.LCID
where
Getutcdate() BETWEEN StartDate AND EndDate
) AS T
where RN BETWEEN @StartIndex AND (@StartIndex + @MaxItems -1)
select * from
(select Row_number() OVER(order by StartDate) as RN, Message
from [Ticker] as T
where
LCID = dbo.PubLCID1(@XLanguage, @XLocale) AND
Getutcdate() BETWEEN StartDate AND EndDate
) AS T
where RN BETWEEN @StartIndex AND (@StartIndex + @MaxItems -1)
[Culture] has PK on XLang,Xloc, [Ticker] has PK on LCID,Id (Id is artificial) and IX on StartDare,EndDate,LCID -- as close to something real as one can get in a few lines.