I am using SQL Server 2008R2.
I’ve got the following setup:
-- Query #1
SELECT * FROM
Product P
INNER JOIN ProductComments C ON C.ProductId = P.ProductId
-- Query #2
SELECT * FROM
GetAllProducts() P
CROSS APPLY GetCommentsOfProduct(P.ProductId) C
where GetAllProducts() is
CREATE FUNCTION GetAllProducts
(
)
RETURNS TABLE
AS
RETURN
(
SELECT * FROM Product
)
and GetCommentsOfProduct(P.ProductId) is
CREATE FUNCTION [dbo].[GetCommentsOfProduct]
(
@ProductId int
)
RETURNS TABLE
AS
RETURN
(
SELECT * FROM ProductComments WHERE ProductId = @ProductId
)
Both query #1 and query #2 result in the exact same actual execution plan and return the same result. Their query costs are both 50% relative to batch. Does this mean, that the SQL query optimizer translates these queries into the same query? And why is there no overhead for calling the UDFs? And does it mean I can structure all of my tables into UDFs and will have no performance issues even when doing JOIN operations? Do you know of any downsides?
There are multiple ways to write a table-valued function. The syntax you’re using, with
AS RETURN, is an “inline table-valued function”. This is equivalent to a view. SQL Server will expand the function when executing the statement. There is no overhead for calling this kind of function.A “multi-statement table-valued function” is not equivalent to a view. The optimizer cannot “inline” the multiple statements, so a “multi-statement TVL” often incurs significant overhead.