I was having a horrible time today trying to get a query to perform the way I would expect. I had to make a slight change to a table valued function that lives in the query yesterday and that change created a huge performance impact on the query. After evaluating the execution plan and looking at statistics IO and Time I found that because I changed the function to return a table variable instead of just a result set it was doing a full scan on one of the tables being queried.
My question is why would having it return the table (TableVariable) instead of just a Select / Result set cause such a big change to the plan?
Stumped….
Returning a Table Variable will make it a multi-statement table valued function and can be bad for performance due to the fact that it’s treated like a table except there are no statistics available for SQL Server to base a good execution plan on – so it will estimate the function as returning a very small number of rows. If it returns a larger number of rows, then therefore the plan generated could be a lot less than optimal.
Whereas, returning just a SELECT makes it an inline table valued function – think of it more as a view. In this case, the actual underlying tables get brought into the main query and a better execution plan can be generated based on proper statistics. You’ll notice that in this case, the execution plan will NOT have a mention of the function at all as it’s basically just merged the function into the main query.
There’s a great reference on it on MSDN by CSS SQL Server Engineers including (quote):