सीक और आप विभाजन किए गए तालिकाओं पर स्कैन करेंगे ...


22

मैंने ये लेख PCMag में इट्ज़िक बेन-गण द्वारा पढ़ा है :

सीक एंड यू शैल स्कैन पार्ट I: जब ऑप्टिमाइज़र सीक को ऑप्टिमाइज़ नहीं करता है
और आप स्कैन II भाग: आरोही कुंजी

वर्तमान में हमारे सभी विभाजित तालिकाओं के साथ "ग्रुपेड मैक्स" समस्या है। हम अधिकतम (आईडी) प्राप्त करने के लिए प्रदान की जाने वाली ट्रिक इट्ज़िक बेन-गण का उपयोग करते हैं , लेकिन कभी-कभी यह बस नहीं चलता है:

DECLARE @MaxIDPartitionTable BIGINT
SELECT  @MaxIDPartitionTable = ISNULL(MAX(IDPartitionedTable), 0)
FROM    ( SELECT    *
          FROM      ( SELECT    partition_number PartitionNumber
                      FROM      sys.partitions
                      WHERE     object_id = OBJECT_ID('fct.MyTable')
                                AND index_id = 1
                    ) T1
                    CROSS APPLY ( SELECT    ISNULL(MAX(UpdatedID), 0) AS IDPartitionedTable
                                  FROM      fct.MyTable s
                                  WHERE     $PARTITION.PF_MyTable(s.PCTimeStamp) = PartitionNumber
                                            AND UpdatedID <= @IDColumnThresholdValue
                                ) AS o
        ) AS T2;
SELECT @MaxIDPartitionTable 

मुझे यह योजना मिलती है

यहाँ छवि विवरण दर्ज करें

लेकिन 45 मिनट के बाद, रीड्स को देखें

reads          writes   physical_reads
12,949,127        2       12,992,610

कि मैं से बाहर निकलना sp_whoisactive

आम तौर पर यह बहुत जल्दी चलता है, लेकिन आज नहीं।

संपादित करें: विभाजन के साथ तालिका संरचना:

CREATE PARTITION FUNCTION [MonthlySmallDateTime](SmallDateTime) AS RANGE RIGHT FOR VALUES (N'2000-01-01T00:00:00.000', N'2000-02-01T00:00:00.000' /* and many more */)
go
CREATE PARTITION SCHEME PS_FctContractualAvailability AS PARTITION [MonthlySmallDateTime] TO ([Standard], [Standard])
GO
CREATE TABLE fct.MyTable(
    MyTableID BIGINT IDENTITY(1,1),
    [DT1TurbineID] INT NOT NULL,
    [PCTimeStamp] SMALLDATETIME NOT NULL,
    Filler CHAR(100) NOT NULL DEFAULT 'N/A',
    UpdatedID BIGINT NULL,
    UpdatedDate DATETIME NULL
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED 
(
    [DT1TurbineID] ASC,
    [PCTimeStamp] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, DATA_COMPRESSION = ROW) ON [PS_FctContractualAvailability]([PCTimeStamp])
) ON [PS_FctContractualAvailability]([PCTimeStamp])

GO

CREATE UNIQUE NONCLUSTERED INDEX [IX_UpdatedID_PCTimeStamp] ON [fct].MyTable
(
    [UpdatedID] ASC,
    [PCTimeStamp] ASC
)
INCLUDE (   [UpdatedDate]) 
WHERE ([UpdatedID] IS NOT NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, DATA_COMPRESSION = ROW) ON [PS_FctContractualAvailability]([PCTimeStamp])
GO

जवाबों:


28

मूल मुद्दा यह है कि इंडेक्स सीक का शीर्ष ऑपरेटर द्वारा पालन नहीं किया जाता है। यह एक अनुकूलन है जो आमतौर पर तब पेश किया जाता है जब साधक MIN\MAXसमुच्चय के लिए सही क्रम में पंक्तियों को लौटाता है ।

यह अनुकूलन इस तथ्य का फायदा उठाता है कि न्यूनतम / अधिकतम पंक्ति आरोही या अवरोही क्रम में पहली है। यह भी हो सकता है कि आशावादी विभाजन विभाजन के लिए इस अनुकूलन को लागू नहीं कर सकता है; मैं भूल गया।

वैसे भी, मुद्दा यह है कि इस परिवर्तन के बिना, निष्पादन योजना S.UpdatedID <= @IDColumnThresholdValueवांछित विभाजन के प्रति वांछित एक पंक्ति के बजाय, प्रत्येक पंक्ति को संसाधित करने वाली प्रक्रिया को समाप्त कर देती है ।

आपने प्रश्न में तालिका, सूचकांक या विभाजन की परिभाषा नहीं दी है, इसलिए मैं बहुत अधिक विशिष्ट नहीं हो सकता। आपको जांचना चाहिए कि आपका सूचकांक ऐसे परिवर्तन का समर्थन करेगा। अधिक या कम समान रूप से, आप MAXएक के रूप में भी व्यक्त कर सकते हैं TOP (1) ... ORDER BY UpdatedID DESC

यदि यह एक सॉर्ट (एक टॉपएन सॉर्ट सहित ) में परिणाम करता है , तो आप जानते हैं कि आपका सूचकांक सहायक नहीं है। उदाहरण के लिए:

SELECT
    @MaxIDPartitionTable = ISNULL(MAX(T2.IDPartitionedTable), 0)
FROM    
( 
    SELECT
        O.IDPartitionedTable
    FROM      
    ( 
        SELECT
            P.partition_number AS PartitionNumber
        FROM sys.partitions AS P
        WHERE 
            P.[object_id] = OBJECT_ID(N'fct.MyTable', N'U')
            AND P.index_id = 1
    ) AS T1
    CROSS APPLY 
    (    
        SELECT TOP (1) 
            S.UpdatedID AS IDPartitionedTable
        FROM fct.MyTable AS S
        WHERE
            $PARTITION.PF_MyTable(S.PCTimeStamp) = T1.PartitionNumber
            AND S.UpdatedID <= @IDColumnThresholdValue
        ORDER BY
            S.UpdatedID DESC
    ) AS O
) AS T2;

इस योजना का आकार यह होना चाहिए:

वांछित योजना आकार

इंडेक्स सीक के नीचे शीर्ष पर ध्यान दें। यह प्रसंस्करण को प्रति पंक्ति एक पंक्ति में सीमित करता है।

या, विभाजन संख्या रखने के लिए एक अस्थायी तालिका का उपयोग कर:

CREATE TABLE #Partitions
(
    partition_number integer PRIMARY KEY CLUSTERED
);

INSERT #Partitions
    (partition_number)
SELECT
    P.partition_number AS PartitionNumber
FROM sys.partitions AS P
WHERE 
    P.[object_id] = OBJECT_ID(N'fct.MyTable', N'U')
    AND P.index_id = 1;

SELECT
    @MaxIDPartitionTable = ISNULL(MAX(T2.UpdatedID), 0)
FROM #Partitions AS P
CROSS APPLY 
(
    SELECT TOP (1) 
        S.UpdatedID
    FROM fct.MyTable AS S
    WHERE
        $PARTITION.PF_MyTable(S.PCTimeStamp) = P.partition_number
        AND S.UpdatedID <= @IDColumnThresholdValue
    ORDER BY
        S.UpdatedID DESC
) AS T2;

DROP TABLE #Partitions;

साइड नोट: आपकी क्वेरी में सिस्टम टेबल एक्सेस करना समानता को रोकता है। यदि यह महत्वपूर्ण है, तो एक अस्थायी तालिका में विभाजन संख्याओं को भौतिक बनाने पर विचार करें, फिर APPLYउसी से। समानांतरवाद सामान्य रूप से इस पैटर्न (सही अनुक्रमण के साथ) में मददगार नहीं है, लेकिन इसका उल्लेख नहीं करना मेरे लिए याद रखना होगा।

साइड नोट 2: एक सक्रिय कनेक्ट आइटम है जो MIN\MAXविभाजित वस्तुओं के लिए समुच्चय और शीर्ष के लिए अंतर्निहित समर्थन का अनुरोध करता है।

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