Analysis of performance problems caused by join of table-valued function _mssql

Source: Internet
Author: User
Tags joins

Table-Valued functions

SQL Server provides functions similar to other programming languages, and the nature of a function is usually encapsulated by a piece of code and returns a value. In SQL Server, a function can return a collection, in addition to a simple data type (Int, varchar, and so on), and return a table.
The table-valued function is divided into an inline user-defined table-valued function and a user-defined table-valued function (hereinafter referred to as a table-valued function, omitting the "user-defined" four words), depending on whether the collection is returned directly or the definition is returned.

Inline table-valued function
Inline table-valued functions are no different from normal functions, except that the return result is a collection (table) rather than a simple data type, and a simple inline table-valued function, as shown in Listing 1 (excerpt from MSDN).

CREATE FUNCTION sales.ufn_customernamesinregion
(@Region nvarchar)
RETURNS table as return
(
SELECT DISTINCT s.name as Store, a.city
From Sales.Store as S
INNER JOIN person.businessentityaddress as Bea on 
bea. BusinessEntityID = S.businessentityid 
INNER JOIN person.address as a on 
a.addressid = bea. Addressid
INNER JOIN person.stateprovince as SP on 
sp. StateProvinceID = A.stateprovinceid
WHERE sp. Name = @Region
);
Go

Code Listing 1. A simple table-valued function

User-defined table-valued functions
and user-defined table-valued functions. You need to define the returned table structure at the start of the function, and then write any code to manipulate the data, insert it into the defined table structure, and return it, a slightly responsible user-defined table-valued function, as shown in Listing 2 (excerpt from MSDN).

CREATE FUNCTION dbo.ufngetcontactinformation (@ContactID int) RETURNS @retContactInformation TABLE (--Columns Returne D by the function ContactID int PRIMARY KEY NOT null, FirstName nvarchar (m) null, LastName nvarchar (m) NULL, JOBTITL e nvarchar (x) null, ContactType nvarchar () null) as--Returns the "name, last name, job title, and contacts T 
Ype for the specified contacts. 
BEGIN DECLARE @FirstName nvarchar (m), @LastName nvarchar (m), @JobTitle nvarchar (50), @ContactType nvarchar; 
--Get common contact information SELECT @ContactID = BusinessEntityID, @FirstName = FirstName, @LastName = LastName 
From Person.person WHERE BusinessEntityID = @ContactID; --Get Contacts job title SELECT @JobTitle = case-Check for employee when EXISTS (SELECT * from Person.person as P W Here P.businessentityid = @ContactID and P.persontype = ' EM ') THEN (SELECT jobtitle from HumanResources.Employee as e W Here E.businessentityid = @ContactID)--Check for vendor 
When EXISTS (SELECT * from Person.person as P WHERE P.businessentityid = @ContactID and P.persontype = ' VC ') THEN (Sele CT Ct. Name from Person.contacttype as CT INNER JOIN person.businessentitycontact as Bec on Bec. Contacttypeid = Ct. Contacttypeid WHERE Bec. PersonID = @ContactID)--Check for store when EXISTS (SELECT * from Person.person as P WHERE P.businessentityid = @Co Ntactid and P.persontype = ' SC ') THEN (SELECT Ct. Name from Person.contacttype as CT INNER JOIN person.businessentitycontact as Bec on Bec. Contacttypeid = Ct. Contacttypeid WHERE Bec. 
PersonID = @ContactID) ELSE NULL end; --Get contacts type SET @ContactType = case-Check for employee when EXISTS (SELECT * from Person.person as P WHERE P.businessentityid = @ContactID and P.persontype = ' EM ') THEN ' Employee '--Check for vendor when EXISTS (SELECT * FROM Person.person as P WHERE P.businessentityid = @ContactID and P.persontype = ' VC ') THEN ' Vendor contacts '--Check for St Ore when EXISTS (SeleCT * from Person.person as P WHERE P.businessentityid = @ContactID and P.persontype = ' SC ') THEN ' Store contacts '--Che CK for individual consumer when EXISTS (SELECT * from Person.person as P WHERE P.businessentityid = @ContactID and P.pers Ontype = ' in ') THEN ' Consumer '--Check for general contacts when EXISTS (SELECT * from Person.person as P WHERE p.busin 
Essentityid = @ContactID and P.persontype = ' GC ') THEN ' general contacts ' end; --Return of the information to the caller IF @ContactID was not NULL BEGIN INSERT @retContactInformation SELECT @ContactI 
D, @FirstName, @LastName, @JobTitle, @ContactType; 
End; 
return; 
End; Go

Code Order 2. Table-valued function

Why should I use table-valued functions
It seems that the table-valued function does not differ from the stored procedure, but in fact it is different. is because table-valued functions can be used to write to other queries, and stored procedures are not. In addition, table-valued functions combined with the Apply operator can greatly simplify the connection operation.

Consider overriding a table-valued function if the stored procedure meets one of the following criteria.

• Stored procedure logic is very simple, just a SELECT statement, without the view of the reason only because of the need for parameters.
• There is no update operation in the stored procedure.
• There is no dynamic SQL in the stored procedure.
• Only one result set is returned in the stored procedure.
• The primary purpose of the stored procedure is to produce a temporary result set and to save the result set to a temporary table for other queries to invoke.

Problems with user-defined table-valued functions

Table-valued functions are different from inline table-valued functions, and inline table-valued functions are more like a view during processing. This means that in the query optimization phase, inline table-valued functions can participate in the optimization of the query optimizer, such as pushing the filter condition (Where) to the bottom of the algebra tree, which means that you can join it first, This enables the use of index lookups to reduce IO and thereby improve performance.
Let's take a look at a simple example. The following code example is a simple example of a join with a table-valued function:
First we create table-valued functions, which are inline table-valued functions and table-valued functions, as shown in code Listing 3.

--Create a table-valued number of rows creating 
FUNCTION tvf_multi_test () 
RETURNS @SaleDetail table (ProductId INT) as 
BEGIN 
INSERT into @SaleDetail 
SELECT ProductID 
sales.salesorderheader soh 
INNER JOIN Sales.SalesOrderDetail sod on Soh. SalesOrderID = Sod. SalesOrderID 
return End 
--Creates an inline table-valued function tvf_inline_test create function 
() 
RETURNS table 
As 
return 
SELECT ProductID from 
sales.salesorderheader Soh 

Code Listing 3. To create two different functions

Now, we use the same query to join the two table-valued functions, as shown in Listing 4 of the code.

--table-valued functions do join 
SELECT C.personid, 
prod.name, 
COUNT (*) ' Numer ' 
from Person.businessentitycontact c 
INNER JOIN dbo.tvf_multi_test () tst on c.personid = TST. ProductId 
INNER JOIN production.product prod on TST. ProductId = Prod. ProductID 
GROUP by C.personid, 
prod.name 
 
--inline table-valued functions do join 
SELECT C.personid, 
prod.name, 
COUNT (*) ' Numer of unit ' from 
person.businessentitycontact c 
INNER JOIN dbo.tvf_inline_test () TST on C.personid = TST. ProductId 
INNER JOIN production.product prod on TST. ProductId = Prod. ProductID 
GROUP by C.personid, 
Prod.name

Code Listing 4. Table-valued functions and inline table-valued functions do join

The cost of execution is shown in Figure 1.

Figure 1. Cost of two ways

From the IO point of view, it is obvious that the suboptimal execution plan was selected, and Businessentitycontact selected 121,317 lookups instead of one. The inline table function correctly knows that the cost of scanning once is much lower than the first lookup.

The root of that problem is the inline table-valued function, which, for SQL Server, is the same as the view, which means that inline table-valued functions can participate in the algebraic operations of a logical execution plan (or an algebraic tree optimization), which means that the inward table can be further split (as shown in Figure 1, the second inline table query, The execution plan specifically knows that the SalesOrderHeader table and the SalesOrderDetail table are in the introverted table, and because the query selects only one column, the plan optimization is performed until the SalesOrderHeader table can be scanned without scanning, and for the inline table-valued function, The execution plan is fully aware of the indexes on the tables involved and the metadata such as related statistics.
On the other hand, table-valued functions, as shown in the first part of Figure 1, are a black box for the entire execution plan, with neither statistics nor indexes. The table-valued function is not known in the execution plan (the temporary table in Figure 1 is #ae4e5168). Rather than a concrete indication), the result set SQL Server assumes a very small result for the entire execution plan, and when the table-valued function returns more results (as shown in this example), Will result in a worse execution plan.
So to sum up, when a table-valued function returns minimal results, it may have no effect on performance, but if the return result is slightly more, it will certainly affect the quality of the execution plan.

How to Handle
first, in SQL Server, we'll find the existing and table-valued functions to join the statement, through the mining execution plan, we can find the class of statements, using the code as shown in Listing 5.

With XmlNamespaces (' Http://schemas.microsoft.com/sqlserver/2004/07/showplan ' as P) 
SELECT St.text, 
Qp.query_plan from 
( 
SELECT the sys.dm_exec_query_stats order by 
Total_worker_time DESC 
As QS 
CROSS apply Sys.dm_exec_sql_text (Qs.sql_handle) as St 
CROSS apply sys.dm_exec_query_plan (qs.plan_ HANDLE) as QP 
WHERE qp.query_plan.exist ('//p:relop[contains (@LogicalOp, Join ")]/*/p:relop[(@LogicalOp [. =] table-valued function "]) = 1

Code Listing 5. Find the query that joins the table-valued function from the execution plan cache

The result is shown in Figure 2.

Figure 2 Query that already exists in the execution plan cache and that joins the table-valued function

Summary
This article describes the concept of table-valued functions, why table-valued functions affect performance and find queries that join the table-valued function in the execution plan cache. A query that has a very small number of rows returned by apply or table-valued functions may not be affected. However, a join to a table-valued function that returns more results can cause performance problems, so if possible, overriding the table-valued function as an inline table-valued function or depositing the results of a table-valued function in a temporary table can improve performance.

Resources:

http://www.brentozar.com/blitzcache/tvf-join/

http://blogs.msdn.com/b/psssql/archive/2010/10/28/ Query-performance-and-multi-statement-table-valued-functions.aspx? Commentposted=true#commentmessage

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.