क्वेरी बहुत धीरे-धीरे निष्पादित हो रही है, क्या आगे इसे सुधारने का कोई तरीका है?


9

मेरे पास निम्न क्वेरी है, और बहुत सारे SUMफ़ंक्शन कॉल के कारण, मेरी क्वेरी बहुत धीमी गति से चल रही है। मेरे डेटाबेस में बहुत सारे रिकॉर्ड हैं और मैं वर्तमान वर्ष और पिछले वर्ष (पिछले 30 दिन, अंतिम 90 दिन और पिछले 365 दिन) से प्रत्येक के लिए एक रिपोर्ट प्राप्त करना चाहूंगा:

SELECT 
    b.id as [ID]
    ,d.[Title] as [Title]
    ,e.Class as [Class]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 30 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 30 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 90 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 90 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 365 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 365 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 30 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 30 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 90 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 90 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 365 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 365 Days Col2]


    FROM 
    tb1 a
INNER JOIN 
    tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN 
    tb3 c on b.fid = c.col5
INNER JOIN       
    tb4 d on c.id = d.col6
INNER JOIN 
    tb5 e on c.col7 = e.id
GROUP BY
    b.id, d.Title, e.Class

किसी को भी पता नहीं है कि मैं तेजी से चलाने के लिए अपनी क्वेरी कैसे सुधार सकता हूं?

संपादित करें: मुझे DATEADDफ़ंक्शन कॉल को whereस्टेटमेंट में स्थानांतरित करने और पहले दो साल लोड करने के लिए प्रोत्साहित किया गया था, फिर उन्हें कॉलम में फ़िल्टर करें, लेकिन मुझे यकीन नहीं है कि सुझाए गए उत्तर को निष्पादित किया गया है और काम करता है, यह यहां पाया जा सकता है: https: // stackoverflow। com / एक / 59944426/12536284

यदि आप उपरोक्त समाधान से सहमत हैं, तो कृपया मुझे दिखाएं कि मैं इसे अपनी वर्तमान क्वेरी में कैसे लागू कर सकता हूं?

सिर्फ FYI करें, मैं इस SP का C #, Entity Framework (DB-First) में उपयोग कर रहा हूँ, कुछ इस प्रकार है:

var result = MyDBEntities.CalculatorSP();

4
हमें अपनी निष्पादन योजना दिखाएं ...
डेल के

1
कुछ भी - क्वेरी को धीमा कर सकता है
Fabio


2
फिर, कृपया निष्पादन योजना पोस्ट करें।
SQL पुलिस

2
फिर भी हम देख नहीं रहे हैं Execution Plan। कृपया इसे पोस्ट करें
अरुण पलानीसामी

जवाबों:


10

जैसा कि यह पहले ही उल्लेख किया गया है, निष्पादन योजना वास्तव में इस मामले में सहायक होगी। आपने जो दिखाया है, उसके आधार पर आपको लगता है कि आपने कुल 15 कॉलमों में से 12 कॉलम निकाले हैं tb1 (a), ताकि आप बिना किसी ज्वाइन के अपनी क्वेरी चलाने की कोशिश कर सकें और tb1यह देखने के लिए कि आपकी क्वेरी अपेक्षित रूप से काम कर रही है या नहीं। चूँकि मैं आपके SUM फ़ंक्शन कॉल में कुछ भी गलत नहीं देख सकता, इसलिए मेरा सबसे अच्छा अनुमान है कि आपके पास आपकी जॉन्स के साथ कोई समस्या है, मैं निम्नलिखित करने का सुझाव दूंगा। आप उदाहरण के लिए, अंतिम जुड़ाव को छोड़कर शुरू कर सकते हैं, INNER JOIN tb5 e on c.col7 = e.id और इस तरह इसके बारे में किसी भी संबंधित उपयोग e.Class as [Class]औरe.Classअपने समूह में कथन द्वारा। हम इसे पूरी तरह से बाहर नहीं करने जा रहे हैं, यह सिर्फ यह सुनिश्चित करने के लिए एक परीक्षा है कि क्या समस्या उस के साथ है या नहीं, अगर आपकी क्वेरी बेहतर चलती है और उम्मीद के मुताबिक आप अंतिम शामिल होने के बजाय वर्कअराउंड के रूप में टेम्प टेबल का उपयोग करने का प्रयास कर सकते हैं , कुछ इस तरह:

SELECT *
INTO #Temp
FROM
  (
     select * from tb5
  ) As tempTable;

SELECT 
    b.id as [ID]
    ,d.[Title] as [Title]
    ,e.Class as [Class]

    -- SUM Functions

FROM 
    tb1 a
INNER JOIN 
    tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN 
    tb3 c on b.fid = c.col5
INNER JOIN       
    tb4 d on c.id = d.col6
INNER JOIN 
    #Temp e on c.col7 = e.id
GROUP BY
    b.id, d.Title, e.Class

असल में, अस्थायी तालिकाएँ वे तालिकाएँ होती हैं जो अस्थायी रूप से SQL सर्वर पर मौजूद होती हैं। अस्थायी परिणाम कई बार एक्सेस किए गए तात्कालिक परिणाम सेटों को संग्रहीत करने के लिए उपयोगी होते हैं। आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं https://www.sqlservertutorial.net/sql-server-basics/sql-server-temporary-tables/ और यहाँ https://codingsight.com/introduction-to-tomporary-tables-in -एस क्यू एल सर्वर/

इसके अलावा, मैं दृढ़ता से अनुशंसा करते हैं, अगर आप संग्रहित प्रक्रिया का उपयोग कर रहे हैं, सेट NOCOUNTकरने के लिए ON, है, यह भी एक महत्वपूर्ण प्रदर्शन को बढ़ावा देने प्रदान कर सकते हैं क्योंकि नेटवर्क यातायात बहुत कम है:

SET NOCOUNT ON
SELECT *
INTO #Temp
-- The rest of code

के आधार पर यह :

सेट नोव ऑन एक सेट स्टेटमेंट है जो उस संदेश को रोकता है जो टी-एसक्यूएल क्वेरी स्टेटमेंट से प्रभावित पंक्तियों की संख्या दर्शाता है। इसका उपयोग संग्रहीत प्रक्रियाओं के भीतर किया जाता है और प्रभावित पंक्तियों संदेश को दिखाने से बचने के लिए ट्रिगर किया जाता है। एक संग्रहीत कार्यविधि के भीतर सेट नोव का उपयोग करके एक महत्वपूर्ण मार्जिन द्वारा संग्रहीत कार्यविधि के प्रदर्शन में सुधार किया जा सकता है।


1
आप क्यों पूरे को कॉपी कृपया उसका वर्णन tb5करने के लिए #Tempमेज और तेजी से शामिल होने से अस्थायी तालिका काम में शामिल होने के tb5लिए सीधे? सुरक्षित रूप से उनमें एक ही डेटा होता है (और #Tempयदि यह मौजूद था तो एक इंडेक्स याद आ सकता है tb5)। मैं वास्तव में समझ नहीं पा रहा हूं कि यह अधिक कुशल क्यों है (सभी के लिए मुझे पता है कि सभी डेटा को कॉपी करने और जुड़ने के लिए यह कम कुशल होना चाहिए )।
जिग

2
@ ज़िग आप इस मामले में सही हैं, लेकिन क्या होगा अगर tb5दूसरे सर्वर में स्थित है? इस मामले में एक अस्थायी तालिका का उपयोग निश्चित रूप से दूसरे सर्वर से सीधे जुड़ने की तुलना में तेज है। यह सिर्फ एक परीक्षण करने और देखने के लिए एक सुझाव था कि क्या कुछ भी बदला है मुझे अतीत में इसी तरह की स्थिति थी, और यह सौभाग्य से लगता है कि अस्थायी तालिका ने ओपी को इस मामले में भी मदद की है।
सलाह अकबरी

2

सबसे अच्छा तरीका एक टेबल वेरिएबल / हैश टेबल में डालना है (यदि पंक्ति की गिनती छोटी है तो टेबल वेरिएबल का उपयोग करें या यदि पंक्ति की गिनती बहुत बड़ी है तो हैश टेबल का उपयोग करें)। फिर एकत्रीकरण को अद्यतन करें और फिर अंत में तालिका चर या हैश तालिका से चुनें। क्वेरी प्लान में देखना आवश्यक है।

DECLARE @MYTABLE TABLE (ID INT, [Title] VARCHAR(500), [Class] VARCHAR(500),
[Current - Last 30 Days Col1] INT, [Current - Last 30 Days Col2] INT,
[Current - Last 90 Days Col1] INT,[Current - Last 90 Days Col2] INT,
[Current - Last 365 Days Col1] INT, [Current - Last 365 Days Col2] INT,
[Last year - Last 30 Days Col1] INT, [Last year - Last 30 Days Col2] INT,
[Last year - Last 90 Days Col1] INT, [Last year - Last 90 Days Col2] INT,
[Last year - Last 365 Days Col1] INT, [Last year - Last 365 Days Col2] INT)



INSERT INTO @MYTABLE(ID, [Title],[Class], 
[Current - Last 30 Days Col1], [Current - Last 30 Days Col2],
[Current - Last 90 Days Col1], [Current - Last 90 Days Col2],
[Current - Last 365 Days Col1], [Current - Last 365 Days Col2],
[Last year - Last 30 Days Col1], [Last year - Last 30 Days Col2],
[Last year - Last 90 Days Col1], [Last year - Last 90 Days Col2],
[Last year - Last 365 Days Col1], [Last year - Last 365 Days Col2]
  )
SELECT    b.id  ,d.[Title] ,e.Class ,0,0,0,0,0,0,0,0,0,0,0,0        
FROM     tb1 a
INNER JOIN   tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN   tb3 c on b.fid = c.col5
INNER JOIN   tb4 d on c.id = d.col6
INNER JOIN  tb5 e on c.col7 = e.id
GROUP BY b.id, d.Title, e.Class

UPDATE T 
SET [Current - Last 30 Days Col1]=K.[Current - Last 30 Days Col1] , 
[Current - Last 30 Days Col2]    =K.[Current - Last 30 Days Col2],
[Current - Last 90 Days Col1]    = K.[Current - Last 90 Days Col1], 
[Current - Last 90 Days Col2]    =K.[Current - Last 90 Days Col2] ,
[Current - Last 365 Days Col1]   =K.[Current - Last 365 Days Col1], 
[Current - Last 365 Days Col2]   =K.[Current - Last 365 Days Col2],
[Last year - Last 30 Days Col1]  =K.[Last year - Last 30 Days Col1],
 [Last year - Last 30 Days Col2] =K.[Last year - Last 30 Days Col2],
[Last year - Last 90 Days Col1]  =K.[Last year - Last 90 Days Col1], 
[Last year - Last 90 Days Col2]  =K.[Last year - Last 90 Days Col2],
[Last year - Last 365 Days Col1] =K.[Last year - Last 365 Days Col1],
 [Last year - Last 365 Days Col2]=K.[Last year - Last 365 Days Col2]
    FROM @MYTABLE T JOIN 
     (
SELECT 
    b.id as [ID]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Current - Last 30 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Current - Last 30 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Current - Last 90 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Current - Last 90 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Current - Last 365 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Current - Last 365 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Last year - Last 30 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Last year - Last 30 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Last year - Last 90 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Last year - Last 90 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Last year - Last 365 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Last year - Last 365 Days Col2]
    FROM     tb1 a
INNER JOIN   tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN   tb3 c on b.fid = c.col5
INNER JOIN   tb4 d on c.id = d.col6
INNER JOIN  tb5 e on c.col7 = e.id
GROUP BY    b.id
) AS K ON T.ID=K.ID


SELECT *
FROM @MYTABLE

0

मुझे लगता है कि tb1 एक बड़ी तालिका है (tb2, tb3, tb4 और tb5 के सापेक्ष)।

यदि हां, तो यह समझ में आता है कि उस तालिका के चयन को प्रतिबंधित करने के लिए (WHERE क्लॉज के साथ)।

यदि केवल tb1 के एक छोटे से हिस्से का उपयोग किया जाता है, उदाहरण के लिए क्योंकि tb2, tb3, tb4 और tb5 के साथ जुड़ने से पंक्तियाँ आवश्यक प्रतिशत को कुछ प्रतिशत तक कम कर देती हैं, तो आपको जाँच करनी चाहिए कि क्या तालिकाओं में आपके द्वारा उपयोग किए जाने वाले स्तंभों पर अनुक्रमित किए गए हैं ।

यदि tb1 के एक बड़े हिस्से का उपयोग किया जाता है, तो यह tb2, tb3, tb4 और tb5 में शामिल होने से पहले इसके परिणामों को समूहित करने के लिए समझ में आता है। नीचे उसी का एक उदाहरण है।

SELECT 
    b.id as [ID]
    ,d.[Title] as [Title]
    ,e.Class as [Class]
    ,SUM(a.[Current - Last 30 Days Col1]) AS [Current - Last 30 Days Col1]
    ,SUM(a.[Current - Last 30 Days Col2]) AS [Current - Last 30 Days Col2]
    ,SUM(a.[Current - Last 90 Days Col1]) AS [Current - Last 90 Days Col1]
    -- etc.
    FROM (
      SELECT a.id, a.col3

      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 30 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 30 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 90 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 90 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 365 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 365 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 30 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 30 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 90 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 90 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 365 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 365 Days Col2]

      FROM  tb1 a
      WHERE a.DateCol >= DATEADD(YEAR,-2,GETDATE())
      GROUP BY a.id, a.col3
    ) AS a
INNER JOIN 
    tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN 
    tb3 c on b.fid = c.col5
INNER JOIN       
    tb4 d on c.id = d.col6
INNER JOIN 
    tb5 e on c.col7 = e.id
GROUP BY
    b.id, d.Title, e.Class

पहले निष्पादन योजना को देखना, और फिर अनुक्रमणिका बनाने और सांख्यिकी को पुन: बनाने पर निर्णय लेना बेहतर होगा।
SQL पुलिस

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

1
आप कुछ जाने बिना "मान लेते हैं"। तो आप अज्ञात के आधार पर एक उत्तर पोस्ट करते हैं। इसलिए नीच। निष्पादन योजना को पोस्ट करके ओपी को अपने प्रश्न में सुधार करने का निर्देश देना बेहतर है।
SQL पुलिस

यह सब मैंने नहीं लिखा। व्यक्तिगत रूप से, मैं केवल तभी डाउनवोट करूंगा यदि उत्तर खराब या गलत है, न कि जब मैं केवल असहमत हूं। लेकिन जवाब देने के लिए धन्यवाद।
गर्ट-

एक तरह से यह गलत है, क्योंकि आप कैसे साबित कर सकते हैं कि यह सही है?
SQL पुलिस


0

ऐसी गणनाओं के अनुकूलन के लिए, आप कुछ मूल्यों के पूर्व-गणना पर विचार करते हैं। पूर्व-गणना का विचार उन पंक्तियों की संख्या को कम करना है जिन्हें पढ़ने या आगे बढ़ने की आवश्यकता है।

इसे प्राप्त करने का एक तरीका अनुक्रमित दृश्य का उपयोग करना है और इंजन को गणनाओं को स्वयं करने के लिए छोड़ दें। इस प्रकार के विचारों की कुछ सीमाएँ होने के कारण, आप एक साधारण तालिका बनाते हैं और इसके बजाय गणना करते हैं। मूल रूप से, यह व्यवसाय की जरूरतों पर निर्भर करता है।

तो, उदाहरण के में मैं के साथ एक मेज बनाने हूँ नीचे RowIDऔर RowDatetimeकॉलम और 1 लाख पंक्तियों डालने। मैं प्रति दिन संस्थाओं की गणना करने के लिए अनुक्रमित दृश्य का उपयोग कर रहा हूं, इसलिए प्रति वर्ष 1 मिलियन पंक्तियों को क्वेरी करने के बजाय मैं इन मैट्रिक्स को गिनने के लिए प्रति वर्ष 365 पंक्तियों को क्वेरी करूंगा।

DROP TABLE IF EXISTS [dbo].[DataSource];
GO

CREATE TABLE [dbo].[DataSource]
(
    [RowID] BIGINT IDENTITY(1,1) PRIMARY KEY
   ,[RowDateTime] DATETIME2
);

GO

DROP VIEW IF EXISTS [dbo].[vw_DataSource];
GO

CREATE VIEW [dbo].[vw_DataSource] WITH SCHEMABINDING
AS
SELECT YEAR([RowDateTime]) AS [Year]
      ,MONTH([RowDateTime]) AS [Month]
      ,DAY([RowDateTime]) AS [Day]
      ,COUNT_BIG(*) AS [Count]
FROM [dbo].[DataSource]
GROUP BY YEAR([RowDateTime])
        ,MONTH([RowDateTime])
        ,DAY([RowDateTime]);
GO

CREATE UNIQUE CLUSTERED INDEX [IX_vw_DataSource] ON [dbo].[vw_DataSource]
(
    [Year] ASC,
    [Month] ASC,
    [Day] ASC
);

GO

DECLARE @min bigint, @max bigint
SELECT @Min=1 ,@Max=1000000

INSERT INTO [dbo].[DataSource] ([RowDateTime])
SELECT TOP (@Max-@Min+1) DATEFROMPARTS(2019,  1.0 + floor(12 * RAND(convert(varbinary, newid()))), 1.0 + floor(28 * RAND(convert(varbinary, newid())))          )       
FROM master..spt_values t1 
CROSS JOIN master..spt_values t2

GO


SELECT *
FROM [dbo].[vw_DataSource]


SELECT SUM(CASE WHEN DATEFROMPARTS([Year], [Month], [Day]) >= DATEADD(MONTH,-1,GETDATE()) THEN [Count] ELSE 0 END) as [Current - Last 30 Days Col1]
      ,SUM(CASE WHEN DATEFROMPARTS([Year], [Month], [Day]) >= DATEADD(QUARTER,-1,GETDATE()) THEN [Count] ELSE 0 END) as [Current - Last 90 Days Col1]
      ,SUM(CASE WHEN DATEFROMPARTS([Year], [Month], [Day]) >= DATEADD(YEAR,-1,GETDATE()) THEN [Count] ELSE 0 END) as [Current - Last 365 Days Col1]
FROM [dbo].[vw_DataSource];

इस तरह के समाधान की सफलता इस बात पर बहुत निर्भर करती है कि डेटा कैसे वितरित किया गया है और आपके पास कितनी पंक्तियाँ हैं। उदाहरण के लिए, यदि आपके पास वर्ष के प्रत्येक दिन के लिए प्रति दिन एक प्रविष्टि है, तो दृश्य और तालिका में पंक्तियों का समान मिलान होगा, इसलिए I / O संचालन कम नहीं होगा।

इसके अलावा, उपरोक्त डेटा को भौतिक बनाने और इसे पढ़ने का एक उदाहरण है। आपके मामले में आपको दृश्य परिभाषा में और कॉलम जोड़ने की आवश्यकता हो सकती है।


0

DatesId पर एक इंडेक्स के साथ अपने डेटा में शामिल होने के लिए मैं एक लुकअप टेबल "डेट्स" टेबल का उपयोग करूंगा। जब मैं ऐतिहासिक डेटा ब्राउज़ करना चाहता हूं तो मैं एक फिल्टर के रूप में तारीखों का उपयोग करता हूं। ज्वाइन तेज है और इसलिए यह फ़िल्टरिंग है क्योंकि डेट्सड को प्राथमिक इंडेक्स (प्राथमिक कुंजी) क्लस्टर किया गया है। अपनी डेटा तालिका के लिए दिनांक कॉलम (जैसे शामिल कॉलम) भी जोड़ें।

दिनांक तालिका में निम्नलिखित कॉलम हैं:

डेट्स, दिनांक, वर्ष, तिमाही, वर्ष, महीना, महीना, महीना, वर्ष, सप्ताह, सप्ताह, दिन, दिन, महीने, दिन, से दिन,

उदाहरण डेटा: 20310409 2031-04-09 2031 2 2031-Q2 4 अप्रैल अप्रैल 2031_15 15 99 9 3 बुधवार

यदि आप इसका एक सीएसवी चाहते हैं तो आप मुझे पीएम कर सकते हैं ताकि आप इसे डेटाबेस में आयात कर सकें, लेकिन मुझे यकीन है कि आप आसानी से इस तरह का कुछ ऑनलाइन पा सकते हैं और अपना खुद का बना सकते हैं।

मैं एक पहचान कॉलम जोड़ता हूं ताकि आप प्रत्येक तिथि के लिए पूर्णांक प्राप्त कर सकें। इससे काम करना थोड़ा आसान हो जाता है, लेकिन आवश्यकता नहीं।

SELECT * FROM dbo.dates where dateIndex BETWEEN (getDateIndexDate(getDate())-30 AND getDateIndexDate(getDate())+0) --30 days ago

यह मुझे आसानी से एक निश्चित अवधि में वापस कूदने की अनुमति देता है। इस पर अपने विचार बनाना काफी आसान है। आप ROW_NUMBER () फ़ंक्शन का उपयोग वर्ष, सप्ताह, आदि के लिए भी कर सकते हैं।

एक बार जब मुझे मेरे पास चाहिए, मैं डेटा से जुड़ जाता हूं। बहुत तेजी से काम करता है!


0

चूँकि आप हमेशा कई महीनों के मूल्यों पर आधारित होते हैं, इसलिए मैं सबसे पहले एक महीने में समूह से उपखंड में समूह बनाऊंगा। यह एक अस्थायी तालिका का उपयोग करने के समान है। निश्चित नहीं अगर यह वास्तव में आपकी क्वेरी को गति देगा।

SELECT f.id, f.[Title], f.Class,
    SUM(CASE WHEN f.MonthDiff = 1 THEN col1 ELSE 0 END) as [Current - Last 30 Days Col1],
    -- etc
FROM (
    SELECT 
        b.id,
        d.[Title],
        e.Class,
        DateDiff(Month, a.DateCol, GETDATE()) as MonthDiff,
        Sum(a.col1) as col1,
        Sum(a.col2) as col2
    FROM  tb1 a
    INNER JOIN tb2 b on a.id = b.fid and a.col3 = b.col4
    INNER JOIN tb3 c on b.fid = c.col5
    INNER JOIN tb4 d on c.id = d.col6
    INNER JOIN tb5 e on c.col7 = e.id
    WHERE a.DateCol between DATEADD(YEAR,-2,GETDATE() and GETDATE()
    GROUP BY b.id, d.Title, e.Class, DateDiff(Month,  a.DateCol, GETDATE())
) f
group by f.id, f.[Title], f.Class

-2

SQL क्वेरी की गति में सुधार करने के लिए, आपको अनुक्रमित जोड़ना होगा। प्रत्येक सम्मिलित तालिका के लिए, आपको एक सूचकांक जोड़ना होगा।

इस कोड के उदाहरण के लिए oracle:

CREATE INDEX supplier_idx
ON supplier (supplier_name);

यह एक बुरा सुझाव नहीं है। आप ओपी से देखते हैं कि कोई अस्थायी तालिका बिना इंडेक्स के बनाई गई है - INNER JOIN #Temp e on c.col7 = e.id. जबकि उत्तर में सुधार की गुंजाइश है, मुझे नहीं लगता कि इसे एन मस्से में बदल दिया जाना चाहिए। विशेष रूप से एक नए उपयोगकर्ता के लिए।
smoore4

@ smoore4 सहमत, स्पष्ट तर्क के बिना डाउनवॉटिंग के इस विकल्प को हटा दिया जाना चाहिए। इस कार्यक्षमता का एक बड़ा दुरुपयोग है
23
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.