Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

सेट आधारित योजना कई शर्तों के साथ अदिश मान फ़ंक्शन की तुलना में धीमी चलती है

यहां कीवर्ड शब्द है INLINE तालिका मूल्यवान कार्य . आपके पास दो प्रकार के टी-एसक्यूएल तालिकाबद्ध मूल्यवान कार्य हैं:बहु-कथन और इनलाइन। यदि आपका T-SQL फ़ंक्शन BEGIN स्टेटमेंट से शुरू होता है तो यह बकवास - स्केलर या अन्यथा होने वाला है। आप एक अस्थायी तालिका को इनलाइन . में प्राप्त नहीं कर सकते तालिका मूल्यवान फ़ंक्शन इसलिए मुझे लगता है कि आप स्केलर से मल्टी-स्टेटमेंट टेबल वैल्यू फ़ंक्शन में गए हैं जो शायद बदतर होगा।

आपका इनलाइन टेबल वैल्यूड फंक्शन (iTVF) कुछ इस तरह दिखना चाहिए:

CREATE FUNCTION [dbo].[Compute_value]
(
  @alpha FLOAT,
  @bravo FLOAT,
  @charle FLOAT,
  @delta FLOAT
)
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT newValue = 
  CASE WHEN @alpha IS NULL OR @alpha = 0 OR @delta IS NULL OR @delta = 0 THEN 0
       WHEN @bravo IS NULL OR @bravo <= 0 THEN 100
       ELSE @alpha * POWER((100 / @delta), 
             (-2 * POWER(@charle * @bravo, DATEDIFF(<unit of measurement>,GETDATE(),'1/1/2000')/365)))
  END
GO;

ध्यान दें, आपके द्वारा पोस्ट किए गए कोड में, आपका DATEDIFF स्टेटमेंट में datepart मौजूद नहीं है पैरामीटर। अगर कुछ इस तरह दिखना चाहिए:

@x int = DATEDIFF(DAY, GETDATE(),'1/1/2000')   

थोड़ा और आगे जाना - यह समझना महत्वपूर्ण है कि आईटीवीएफ टी-एसक्यूएल स्केलर मूल्यवान उपयोगकर्ता-परिभाषित कार्यों से बेहतर क्यों हैं। ऐसा इसलिए नहीं है क्योंकि टेबल वैल्यू वाले फंक्शन स्केलर वैल्यूड फंक्शन्स की तुलना में तेज़ होते हैं, ऐसा इसलिए होता है क्योंकि माइक्रोसॉफ्ट के टी-एसक्यूएल इनलाइन फ़ंक्शंस का कार्यान्वयन टी-एसक्यूएल फ़ंक्शंस के कार्यान्वयन से तेज़ होता है जो इनलाइन नहीं होते हैं। निम्नलिखित तीन कार्यों पर ध्यान दें जो समान कार्य करते हैं:

-- Scalar version
CREATE FUNCTION dbo.Compute_value_scalar
(
  @alpha FLOAT,
  @bravo FLOAT,
  @charle FLOAT,
  @delta FLOAT
)
RETURNS FLOAT
AS
BEGIN
    IF @alpha IS NULL OR @alpha = 0 OR @delta IS NULL OR @delta = 0 
    RETURN 0

    IF @bravo IS NULL OR @bravo <= 0
        RETURN 100

    IF (@charle + @delta) / @bravo <= 0
        RETURN 100
    DECLARE @x int = DATEDIFF(dd, GETDATE(),'1/1/2000')     
    RETURN @alpha * POWER((100 / @delta), (-2 * POWER(@charle * @bravo, @x/365)))
END
GO

-- multi-statement table valued function 
CREATE FUNCTION dbo.Compute_value_mtvf
(
  @alpha FLOAT,
  @bravo FLOAT,
  @charle FLOAT,
  @delta FLOAT
)
RETURNS  @sometable TABLE (newValue float) AS 
    BEGIN
    INSERT @sometable VALUES
(
  CASE WHEN @alpha IS NULL OR @alpha = 0 OR @delta IS NULL OR @delta = 0 THEN 0
       WHEN @bravo IS NULL OR @bravo <= 0 THEN 100
       ELSE @alpha * POWER((100 / @delta), 
             (-2 * POWER(@charle * @bravo, DATEDIFF(DAY,GETDATE(),'1/1/2000')/365)))
  END
)
RETURN;
END
GO

-- INLINE table valued function
CREATE FUNCTION dbo.Compute_value_itvf
(
  @alpha FLOAT,
  @bravo FLOAT,
  @charle FLOAT,
  @delta FLOAT
)
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT newValue = 
  CASE WHEN @alpha IS NULL OR @alpha = 0 OR @delta IS NULL OR @delta = 0 THEN 0
       WHEN @bravo IS NULL OR @bravo <= 0 THEN 100
       ELSE @alpha * POWER((100 / @delta), 
             (-2 * POWER(@charle * @bravo, DATEDIFF(DAY,GETDATE(),'1/1/2000')/365)))
  END
GO

अब कुछ नमूना डेटा और प्रदर्शन परीक्षण के लिए:

SET NOCOUNT ON;
CREATE TABLE #someTable (alpha FLOAT, bravo FLOAT, charle FLOAT, delta FLOAT);
INSERT #someTable
SELECT TOP (100000)
  abs(checksum(newid())%10)+1, abs(checksum(newid())%10)+1, 
  abs(checksum(newid())%10)+1, abs(checksum(newid())%10)+1
FROM sys.all_columns a, sys.all_columns b;

PRINT char(10)+char(13)+'scalar'+char(10)+char(13)+replicate('-',60);
GO
DECLARE @st datetime = getdate(), @z float;

SELECT @z = dbo.Compute_value_scalar(t.alpha, t.bravo, t.charle, t.delta)
FROM #someTable t;

PRINT DATEDIFF(ms, @st, getdate());
GO

PRINT char(10)+char(13)+'mtvf'+char(10)+char(13)+replicate('-',60);
GO
DECLARE @st datetime = getdate(), @z float;

SELECT @z = f.newValue
FROM #someTable t
CROSS APPLY dbo.Compute_value_mtvf(t.alpha, t.bravo, t.charle, t.delta) f;

PRINT DATEDIFF(ms, @st, getdate());
GO

PRINT char(10)+char(13)+'itvf'+char(10)+char(13)+replicate('-',60);
GO
DECLARE @st datetime = getdate(), @z float;

SELECT @z = f.newValue
FROM #someTable t
CROSS APPLY dbo.Compute_value_itvf(t.alpha, t.bravo, t.charle, t.delta) f;

PRINT DATEDIFF(ms, @st, getdate());
GO

परिणाम:

scalar
------------------------------------------------------------
2786

mTVF
------------------------------------------------------------
41536

iTVF
------------------------------------------------------------
153

स्केलर udf 2.7 सेकंड, mtvf के लिए 41 सेकंड और iTVF के लिए 0.153 सेकंड तक चला। यह समझने के लिए कि आइए अनुमानित निष्पादन योजनाओं को क्यों देखें:

जब आप वास्तविक निष्पादन योजना को देखते हैं तो आपको यह दिखाई नहीं देता है, लेकिन अदिश udf और mtvf के साथ, अनुकूलक प्रत्येक पंक्ति के लिए कुछ खराब निष्पादित सबरूटीन को कॉल करता है; आईटीवीएफ नहीं करता है। पॉल व्हाइट के करियर में बदलाव का हवाला देते हुए APPLY के बारे में लेख पॉल लिखते हैं:

दूसरे शब्दों में, iTVF ऑप्टिमाइज़र को क्वेरी को उन तरीकों से अनुकूलित करने में सक्षम बनाता है जो उस समय संभव नहीं हैं जब अन्य सभी कोड को निष्पादित करने की आवश्यकता होती है। आईटीवीएफ बेहतर क्यों हैं, इसके कई अन्य उदाहरणों में से एक यह है कि वे तीन उपरोक्त फ़ंक्शन प्रकारों में से केवल एक हैं जो समानता की अनुमति देते हैं। आइए प्रत्येक फ़ंक्शन को एक बार फिर से चलाएं, इस बार वास्तविक निष्पादन योजना चालू होने के साथ और ट्रेसफ्लैग 8649 (जो समानांतर निष्पादन योजना को बाध्य करता है) के साथ:

-- don't need so many rows for this test
TRUNCATE TABLE #sometable;
INSERT #someTable 
SELECT TOP (10)
  abs(checksum(newid())%10)+1, abs(checksum(newid())%10)+1, 
  abs(checksum(newid())%10)+1, abs(checksum(newid())%10)+1
FROM sys.all_columns a;

DECLARE @x float;

SELECT TOP (10) @x = dbo.Compute_value_scalar(t.alpha, t.bravo, t.charle, t.delta)
FROM #someTable t
ORDER BY dbo.Compute_value_scalar(t.alpha, t.bravo, t.charle, t.delta)
OPTION (QUERYTRACEON 8649);

SELECT TOP (10)  @x = f.newValue
FROM #someTable t
CROSS APPLY dbo.Compute_value_mtvf(t.alpha, t.bravo, t.charle, t.delta) f
ORDER BY f.newValue
OPTION (QUERYTRACEON 8649);

SELECT @x = f.newValue
FROM #someTable t
CROSS APPLY dbo.Compute_value_itvf(t.alpha, t.bravo, t.charle, t.delta) f
ORDER BY f.newValue
OPTION (QUERYTRACEON 8649);

निष्पादन योजनाएं:

iTVF की निष्पादन योजना के लिए आप जो तीर देखते हैं, वह समानांतरवाद है - आपके सभी CPU (या आपके SQL इंस्टेंस के जितने MAXDOP सेटिंग्स की अनुमति है) एक साथ काम कर रहे हैं। टी-एसक्यूएल स्केलर और एमटीवीएफ यूडीएफ ऐसा नहीं कर सकते हैं। जब माइक्रोसॉफ्ट इनलाइन स्केलर यूडीएफ पेश करता है तो मैं उन्हें सुझाव दूंगा कि आप क्या कर रहे हैं, लेकिन तब तक:यदि प्रदर्शन वही है जो आप ढूंढ रहे हैं तो इनलाइन जाने का एकमात्र तरीका है और उसके लिए, आईटीवीएफ एकमात्र गेम है शहर में।

ध्यान दें कि मैंने लगातार T-SQL . पर जोर दिया है फ़ंक्शन के बारे में बात करते समय... सीएलआर स्केलर और टेबल वैल्यू फ़ंक्शन ठीक हो सकते हैं लेकिन यह एक अलग विषय है।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. अपने डेटा को क्षैतिज कैसे बनाएं

  2. ALTER TABLE कथन परस्पर विरोधी है

  3. स्क्रिप्ट और संग्रहीत कार्यविधियों को तोड़े बिना किसी स्तंभ का नाम बदलना

  4. T-SQL का उपयोग करके SQL सर्वर डेटाबेस का बैकअप कैसे लें

  5. क्या SQL में LIKE और IN का संयोजन है?