यह फ़ंक्शन प्रकार पर निर्भर करता है:
-
यदि फ़ंक्शन एक इनलाइन तालिका-मूल्यवान फ़ंक्शन है तो इस फ़ंक्शन को "पैरामीटरयुक्त" दृश्य और
SQL Server
माना जाएगा कुछ अनुकूलन कार्य कर सकते हैं। -
यदि फ़ंक्शन बहु-चरण तालिका-मूल्यवान फ़ंक्शन है तो
SQL Server
. के लिए कठिन हैSET STATISTICS IO
. से स्टेटमेंट और आउटपुट को ऑप्टिमाइज़ करने के लिए भ्रामक होगा।
अगले परीक्षण के लिए मैंने AdventureWorks2008
. का उपयोग किया (आप इस डेटाबेस को कोडप्लेक्स से डाउनलोड कर सकते हैं)। इस नमूना डेटाबेस में आपको एक inline table-valued function
मिल सकता है नाम [Sales].[ufnGetCheapestProduct]
:
ALTER FUNCTION [Sales].[ufnGetCheapestProduct](@ProductID INT)
RETURNS TABLE
AS
RETURN
SELECT dt.ProductID
,dt.UnitPrice
FROM
(
SELECT d.SalesOrderDetailID
,d.UnitPrice
,d.ProductID
,ROW_NUMBER() OVER(PARTITION BY d.ProductID ORDER BY d.UnitPrice ASC, d.SalesOrderDetailID) RowNumber
FROM Sales.SalesOrderDetail d
WHERE d.ProductID = @ProductID
) dt
WHERE dt.RowNumber = 1
मैंने [Sales].[ufnGetCheapestProductMultiStep]
नाम से एक नया फ़ंक्शन बनाया है . यह फ़ंक्शन एक multi-step table-valued function
है :
CREATE FUNCTION [Sales].[ufnGetCheapestProductMultiStep](@ProductID INT)
RETURNS @Results TABLE (ProductID INT PRIMARY KEY, UnitPrice MONEY NOT NULL)
AS
BEGIN
INSERT @Results(ProductID, UnitPrice)
SELECT dt.ProductID
,dt.UnitPrice
FROM
(
SELECT d.SalesOrderDetailID
,d.UnitPrice
,d.ProductID
,ROW_NUMBER() OVER(PARTITION BY d.ProductID ORDER BY d.UnitPrice ASC, d.SalesOrderDetailID) RowNumber
FROM Sales.SalesOrderDetail d
WHERE d.ProductID = @ProductID
) dt
WHERE dt.RowNumber = 1;
RETURN;
END
अब, हम अगले परीक्षण चला सकते हैं:
--Test 1
SELECT p.ProductID, p.Name, oa1.*
FROM Production.Product p
OUTER APPLY
(
SELECT dt.ProductID
,dt.UnitPrice
FROM
(
SELECT d.SalesOrderDetailID
,d.UnitPrice
,d.ProductID
,ROW_NUMBER() OVER(PARTITION BY d.ProductID ORDER BY d.UnitPrice ASC, d.SalesOrderDetailID) RowNumber
FROM Sales.SalesOrderDetail d
WHERE d.ProductID = p.ProductID
) dt
WHERE dt.RowNumber = 1
) oa1
--Test 2
SELECT p.ProductID, p.Name, oa2.*
FROM Production.Product p
OUTER APPLY [Sales].[ufnGetCheapestProduct](p.ProductID) oa2
--Test 3
SELECT p.ProductID, p.Name, oa3.*
FROM Production.Product p
OUTER APPLY [Sales].[ufnGetCheapestProductMultiStep](p.ProductID) oa3
और यह SQL Profiler
का आउटपुट है :
निष्कर्ष :आप देख सकते हैं कि OUTER APPLY
के साथ किसी क्वेरी या इनलाइन तालिका-मूल्यवान फ़ंक्शन का उपयोग करना आपको वही प्रदर्शन देगा (तार्किक पढ़ता है)। प्लस:बहु-चरण तालिका-मूल्यवान फ़ंक्शन (आमतौर पर) अधिक महंगे होते हैं
।
नोट :मैं SET STATISTICS IO
. का उपयोग करने की अनुशंसा नहीं करता हूं IO
. को मापने के लिए अदिश और बहु-चरण तालिका के लिए मूल्यवान फ़ंक्शन क्योंकि परिणाम गलत हो सकते हैं। उदाहरण के लिए, इन परीक्षणों के लिए SET STATISTICS IO ON
. से आउटपुट होगा:
--Test 1
Table 'SalesOrderDetail'. Scan count 504, logical reads 1513, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Test 2
Table 'SalesOrderDetail'. Scan count 504, logical reads 1513, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Test 3
Table '#064EAD61'. Scan count 504, logical reads 1008 /*WRONG*/, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.