सीरियल मोड में चल रहे समानांतर निष्पादन-स्टिल के लिए एक स्केलर फ़ंक्शन को टीवीएफ फ़ंक्शन में परिवर्तित किया


10

मेरी क्वेरी में से एक एक रिलीज के बाद धारावाहिक निष्पादन मोड में चल रहा था और मैंने देखा कि दो नए कार्यों का उपयोग एक दृश्य में किया गया था जो कि एप्लिकेशन से उत्पन्न SQL क्वेरी से LINQ में संदर्भित है। इसलिए मैंने उन SCALAR फ़ंक्शंस को TVF फ़ंक्शंस में बदल दिया, लेकिन अभी भी सीरियल मोड में क्वेरी चल रही है।

इससे पहले मैंने स्केलर को टीवीएफ रूपांतरण में कुछ अन्य प्रश्नों में किया है और इसने जबरन सीरियल निष्पादन की समस्या को हल किया है।

यहाँ अदिश कार्य है:

CREATE FUNCTION [dbo].[FindEventReviewDueDate]
(
       @EventNumber VARCHAR(20),
       @EventID VARCHAR(25),
          @EventIDDate BIT
)

RETURNS DateTime
AS
BEGIN

DECLARE @CurrentEventStatus VARCHAR(20)
DECLARE @EventDateTime DateTime
DECLARE @ReviewDueDate DateTime


SELECT @CurrentEventStatus = (SELECT cis.EventStatus
                                 FROM CurrentEventStatus cis 
                                 INNER JOIN Event1 r WITH (NOLOCK) ON (cis.Event1Id = r.Id)
                                 WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)

SELECT @EventDateTime = (SELECT EventDateTime FROM Event1 r 
                          WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)

IF @CurrentEventStatus IN ('0','6') AND EventIDDate = 1
BEGIN

       SET @ReviewDueDate = DATEADD(DAY, 30, @EventDateTime)

       WHILE @ReviewDueDate < getdate() 
             SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)

       DECLARE @EventDateJournalDate DateTime

       SELECT @EventDateJournalDate = (SELECT TOP 1 ij.Date
                                       FROM EventPage_EventJournal ij 
                                       INNER JOIN EventJournalPages p ON ij.PageId = p.Id 
                                       INNER JOIN Journal f ON p.FormId = f.Id 
                                       INNER JOIN Event1 r WITH (NOLOCK) ON (f.Event1Id = r.Id)
                                       WHERE (r.EventNumber = @EventNumber AND r.EventID = @EventID) AND ij.ReviewType = 'Supervisor Monthly Review' ORDER BY ij.Date DESC)

      IF(DATEADD(DAY, 30, @EventDateTime) < getdate() AND
           (@EventDateJournalDate is null OR DATEADD(DAY, 30, @EventDateJournalDate) < getdate()) AND
              DATEADD(DAY, 14, @ReviewDueDate) > DATEADD(DAY, 30, getdate()))
                  SET @ReviewDueDate = DATEADD(DAY, -30, @ReviewDueDate)
         ELSE IF((@EventDateJournalDate is not null ) AND (DATEADD(DAY, 30, @EventDateJournalDate) >= @ReviewDueDate))
                  SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)

END
RETURN @ReviewDueDate

END

यहाँ परिवर्तित TVF फ़ंक्शन है।

CREATE FUNCTION [dbo].[FindEventReviewDueDate_test]
(
       @EventNumber VARCHAR(20),
       @EventID VARCHAR(25),
          @EventIDDate BIT
)

RETURNS @FunctionResultTableVairable TABLE (
 CurrentEventStatus varchar(20),
 Event1DateTime DateTime,
 ReviewDueDate DateTime
 )
AS 
BEGIN

DECLARE @CurrentEventStatus VARCHAR(20)
DECLARE @EventDateTime DateTime
DECLARE @ReviewDueDate DateTime


SELECT @CurrentEventStatus = (SELECT cis.EventStatus
                                 FROM CurrentEventStatus cis 
                                 INNER JOIN Event1 r WITH (NOLOCK) ON (cis.Event1Id = r.Id)
                                 WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)

SELECT @EventDateTime = (SELECT EventDateTime FROM Event1 r 
                          WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)

IF @CurrentEventStatus IN ('0','6') AND EventIDDate = 1
BEGIN

       SET @ReviewDueDate = DATEADD(DAY, 30, @EventDateTime)

       WHILE @ReviewDueDate < getdate() 
             SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)

       DECLARE @EventDateJournalDate DateTime

       SELECT @EventDateJournalDate = (SELECT TOP 1 ij.Date
                                       FROM EventPage_EventJournal ij 
                                       INNER JOIN EventJournalPages p ON ij.PageId = p.Id 
                                       INNER JOIN Journal f ON p.FormId = f.Id 
                                       INNER JOIN Event1 r WITH (NOLOCK) ON (f.Event1Id = r.Id)
                                       WHERE (r.EventNumber = @EventNumber AND r.EventID = @EventID) AND ij.ReviewType = 'Supervisor Monthly Review' ORDER BY ij.Date DESC)

      IF(DATEADD(DAY, 30, @EventDateTime) < getdate() AND
           (@EventDateJournalDate is null OR DATEADD(DAY, 30, @EventDateJournalDate) < getdate()) AND
              DATEADD(DAY, 14, @ReviewDueDate) > DATEADD(DAY, 30, getdate()))
                  SET @ReviewDueDate = DATEADD(DAY, -30, @ReviewDueDate)
         ELSE IF((@EventDateJournalDate is not null ) AND (DATEADD(DAY, 30, @EventDateJournalDate) >= @ReviewDueDate))
                  SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
                   insert into @FunctionResultTableVairable
      select @CurrentEventStatus,@EventDateTime,@ReviewDueDate          

END
return;
END

GO

क्या टीवीएफ फ़ंक्शन के मेरे कार्यान्वयन में कुछ गड़बड़ है जो क्वेरी को समानांतर मोड में चलने से रोक रहा है।

मैं नीचे दिए गए क्वेरी में TVF फ़ंक्शन का उपयोग करता हूं;

select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')

मेरी वास्तविक क्वेरी, जो दृश्य का उपयोग करती है, काफी जटिल है और अगर मैं फ़ंक्शन के भाग को देखने और निष्पादित करने पर टिप्पणी करता हूं, तो क्वेरी समानांतर में चलती है। यह फ़ंक्शन है जो क्वेरी को समानांतर में चलने के लिए मजबूर कर रहा है।

मेरी वास्तविक क्वेरी नीचे प्रारूप में है।

select 
dv.column1,
dv.column2,
---------
---------
--------
(select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')) AS 'Columnx'
from
DemoView dv
Where 
condition1
conditon 2

किसी भी मदद की सराहना की है।


3
क्वेरी प्लान क्या कहता है?
डेविड ब्राउन - Microsoft

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

जवाबों:


5

क्या मेरे स्केलर फ़ंक्शन को इनलाइन टीवीएफ में बदलना संभव है?

हाँ। नीचे जैसा कुछ होगा, वैसा करेंगे।

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

CREATE FUNCTION [dbo].[FindEventReviewDueDateInline] (@EventNumber VARCHAR(20),
                                                      @EventID     VARCHAR(25),
                                                      @EventIDDate BIT)
RETURNS TABLE
AS
    RETURN
      WITH X
           AS (SELECT cis.EventStatus AS CurrentEventStatus,
                      r.EventDateTime
               FROM   CurrentEventStatus cis
                      INNER JOIN Event1 r
                              ON cis.Event1Id = r.Id
               WHERE  r.EventNumber = @EventNumber
                      AND r.EventID = @EventID
                      AND cis.EventStatus IN ( '0', '6' )
                      AND @EventIDDate = 1)
      SELECT X.CurrentEventStatus,
             X.EventDateTime,
             CA4.ReviewDueDate
      FROM   X
             --SET @ReviewDueDate = DATEADD(DAY, 30, @EventDateTime)
             CROSS APPLY(VALUES(DATEADD(DAY, 30, X.EventDateTime))) CA1(ReviewDueDate)
             -- WHILE @ReviewDueDate < getdate() 
             --       SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
             CROSS APPLY(VALUES( IIF(CA1.ReviewDueDate >= GETDATE(), CA1.ReviewDueDate, DATEADD(DAY, 30 * CEILING(( IIF(CAST(GETDATE() AS TIME) > CAST(CA1.ReviewDueDate AS TIME), 1, 0)
                                                                                                           + DATEDIFF(DAY, CA1.ReviewDueDate, GETDATE()) ) / 30.0), CA1.ReviewDueDate)))) CA2(ReviewDueDate)
             --SELECT @EventDateJournalDate = ....
             CROSS APPLY(SELECT TOP 1 ij.Date
                         FROM   EventPage_EventJournal ij
                                INNER JOIN EventJournalPages p
                                        ON ij.PageId = p.Id
                                INNER JOIN Journal f
                                        ON p.FormId = f.Id
                                INNER JOIN Event1 r WITH (NOLOCK)
                                        ON ( f.Event1Id = r.Id )
                         WHERE  ( r.EventNumber = @EventNumber
                                  AND r.EventID = @EventID )
                                AND ij.ReviewType = 'Supervisor Monthly Review'
                         ORDER  BY ij.Date DESC) CA3(EventDateJournalDate)
             -- IF(DATEADD(DAY, 30, @EventDateTime) < getdate()
             CROSS APPLY(VALUES ( CASE
                          WHEN ( DATEADD(DAY, 30, X.EventDateTime) < GETDATE()
                                 AND ( CA3.EventDateJournalDate IS NULL
                                        OR DATEADD(DAY, 30, CA3.EventDateJournalDate) < GETDATE() )
                                 AND DATEADD(DAY, 14, CA2.ReviewDueDate) > DATEADD(DAY, 30, GETDATE()) )
                            THEN DATEADD(DAY, -30, CA2.ReviewDueDate)
                          WHEN( ( CA3.EventDateJournalDate IS NOT NULL )
                                AND ( DATEADD(DAY, 30, CA3.EventDateJournalDate) >= CA2.ReviewDueDate ) )
                            THEN DATEADD(DAY, 30, CA2.ReviewDueDate)
                          ELSE CA2.ReviewDueDate
                        END )) CA4(ReviewDueDate); 

11

फॉरेस्ट ज्यादातर है सही है, लेकिन महीन विवरण हैं:

SQL सर्वर तालिका चर में संशोधनों को समानांतर नहीं कर सकता है, जो आपके फ़ंक्शन का उपयोग करता है।

SQL Server 2017 के इंटरलीव्ड एक्ज़ीक्यूशन से पहले , मल्टी-स्टेटमेंट टेबल वैलिड फ़ंक्शंस से पंक्ति अनुमान बहुत कम थे।

इसका एक दुष्परिणाम यह है कि कम लागत पर योजनाओं को बहुत कम लागत में तैयार किया गया था, और अक्सर समानता के लिए लागत सीमा नहीं टूटती।


1
OKCan आप किसी भी वैकल्पिक समाधान को सुव्यवस्थित करते हैं ताकि मेरी मुख्य क्वेरी समानांतर मोड में चल सके। मेरे स्केलर फ़नसिटॉन पर जाकर, क्या मेरे स्केलर फ़ंक्शन को इनलाइन टीवीएफ में बदलना संभव है?
user9516827

1
@ user9516827 आप कुछ समान करने के लिए शायद कुछ सीटीई को एक साथ चेन कर सकते हैं, लेकिन मुझे नहीं पता कि यह समानांतर चलेगा, बेहतर प्रदर्शन करेगा, आदि इसका परीक्षण करना आपके ऊपर है।
एरिक डार्लिंग

@MartinSmith: मेरी वास्तविक क्वेरी बहुत ही जटिल क्वेरी है जिसमें बहुत सारे जुड़ने और विचारों से जुड़ने आदि का उपयोग किया जाता है। यह फ़ंक्शन मुख्य क्वेरी में एक चुनिंदा कॉलम के लिए उपयोग किया जाता है और इसीलिए मैं उस निश्चित को प्राप्त करने की कोशिश कर रहा था। क्योंकि यह एक LINQ है -SQL (निष्पादित sp_executesql फॉर्म) क्वेरी उत्पन्न करता है और मेरे पास .net कोड को हैक न करने की सीमा है।
धन्यवाद

10

SQL सर्वर मल्टी-स्टेटमेंट TVFs को समानांतर नहीं कर सकता है, जो कि आपका है। केवल इनलाइन TVFs को समानांतर किया जा सकता है।


1
चूंकि मेरे पास चर हैं इसलिए मैं स्केलर फ़ंक्शन को इनलाइन टीवीएफ में परिवर्तित करने में सक्षम नहीं हूं?
user9516827
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.