ज्वलनशील सीमा अशक्त समग्र सूचकांक की तलाश करती है?


14

निम्न स्कीमा और उदाहरण के लिए डेटा

CREATE TABLE T
  (
     A INT NULL,
     B INT NOT NULL IDENTITY,
     C CHAR(8000) NULL,
     UNIQUE CLUSTERED (A, B)
  )

INSERT INTO T
            (A)
SELECT NULLIF(( ( ROW_NUMBER() OVER (ORDER BY @@SPID) - 1 ) / 1003 ), 0)
FROM   master..spt_values 

एक आवेदन 1,000 पंक्ति विखंडू में अनुक्रमित क्रम में इस तालिका से पंक्तियों को संसाधित कर रहा है।

पहली 1,000 पंक्तियाँ निम्नलिखित क्वेरी से प्राप्त की जाती हैं।

SELECT TOP 1000 *
FROM   T
ORDER  BY A, B 

उस सेट की अंतिम पंक्ति नीचे है

+------+------+
|  A   |  B   |
+------+------+
| NULL | 1000 |
+------+------+

क्या कोई प्रश्न लिखने का कोई तरीका है जो सिर्फ उस समग्र सूचकांक कुंजी में खोजता है और फिर 1000 पंक्तियों के अगले भाग को प्राप्त करने के लिए इसका अनुसरण करता है?

/*Pseudo Syntax*/
SELECT TOP 1000 *
FROM   T
WHERE (A, B) is_ordered_after (@A, @B)
ORDER  BY A, B 

मैंने अब तक सबसे कम पढ़े जाने की संख्या 1020 है, लेकिन लगता है कि क्वेरी बहुत दूर है। क्या समान या बेहतर दक्षता का एक सरल तरीका है? शायद एक है कि यह सब एक सीमा में करने के लिए प्रबंधित करता है?

DECLARE @A INT = NULL, @B INT = 1000

;WITH UnProcessed
     AS (SELECT *
         FROM   T
         WHERE  ( EXISTS(SELECT A
                         INTERSECT
                         SELECT @A)
                  AND B > @B )
         UNION ALL
         SELECT *
         FROM   T
         WHERE @A IS NULL AND A IS NOT NULL
         UNION ALL
         SELECT *
         FROM   T
         WHERE A > @A        
         )
SELECT TOP 1000 *
FROM   UnProcessed
ORDER  BY A,
          B 

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


एफडब्ल्यूआईडब्ल्यू: यदि स्तंभ Aबनाया गया है NOT NULLऔर एक समान मूल्य का -1उपयोग किया जाता है, तो इसके बजाय समान निष्पादन योजना निश्चित रूप से सरल लगती है

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

लेकिन योजना में एकल तलाश ऑपरेटर अभी भी एक ही सन्निहित सीमा में ढहने के बजाय दो तलाश करता है और तार्किक रीड बहुत अधिक हैं इसलिए मुझे संदेह है कि शायद यह बहुत अच्छा है जितना इसे मिलेगा?


मेरी गलती। मैं भूल गया कि NULLमूल्य हमेशा पहले होते हैं। (इसके विपरीत मान लिया गया।) फिडल
ypercube

हां ओरेकल अलग है मेरा मानना ​​है।
मार्टिन स्मिथ


@ypercube - एसक्यूएल सर्वर सिर्फ उस के लिए एक आदेशित स्कैन देता है दुर्भाग्य से इसलिए आवेदन द्वारा पहले से संसाधित सभी पंक्तियों को फिर से पढ़ता है (तार्किक रीड 2015)। यह की पहली कुंजी को में की तलाश नहीं है(NULL, 1000 )
मार्टिन स्मिथ

2 अलग स्थितियों के साथ @A, यह शून्य है या नहीं, ऐसा लगता है कि यह स्कैन नहीं करता है। लेकिन मैं यह नहीं समझ सकता कि क्या योजनाएँ आपकी क्वेरी से बेहतर हैं। फिडल -2
ypercubeᵀᴹ

जवाबों:


21

क्या कोई प्रश्न लिखने का कोई तरीका है जो सिर्फ उस समग्र सूचकांक कुंजी में खोजता है और फिर 1000 पंक्तियों के अगले भाग को प्राप्त करने के लिए इसका अनुसरण करता है?

मेरा एक पसंदीदा समाधान एक APIकर्सर का उपयोग करना है:

SET NOCOUNT ON;
SET STATISTICS IO ON;

DECLARE 
    @cur integer,
    -- FAST_FORWARD, AUTO_FETCH, AUTO_CLOSE, CHECK_ACCEPTED_TYPES, FAST_FORWARD_ACCEPTABLE
    @scrollopt integer = 16 | 8192 | 16384 | 32768 | 1048576,
    -- READ_ONLY, CHECK_ACCEPTED_OPTS, READ_ONLY_ACCEPTABLE
    @ccopt integer = 1 | 32768 | 65536, 
    @rowcount integer = 1000,
    @rc integer;

-- Open the cursor and return (up to) the first 1000 rows
EXECUTE @rc = sys.sp_cursoropen
    @cur OUTPUT,
    N'
    SELECT A, B, C
    FROM T
    ORDER BY A, B;
    ',
    @scrollopt OUTPUT,
    @ccopt OUTPUT,
    @rowcount OUTPUT;

IF @rc <> 16 -- FastForward cursor automatically closed
BEGIN
    -- Name the cursor so we can use CURSOR_STATUS
    EXECUTE sys.sp_cursoroption
        @cur, 
        2, 
        'MyCursorName';

    -- Until the cursor auto-closes
    WHILE CURSOR_STATUS('global', 'MyCursorName') = 1
    BEGIN
        EXECUTE sys.sp_cursorfetch
            @cur,
            2,
            0,
            1000;
    END;
END;

SET STATISTICS IO OFF;

समग्र रणनीति एक एकल स्कैन है जो कॉल के बीच अपनी स्थिति को याद करती है। APIकर्सर का उपयोग करने का मतलब है कि हम एक बार में एक T-SQLकर्सर के बजाय पंक्तियों के एक ब्लॉक को वापस कर सकते हैं :

निष्पादन की योजना

STATISTICS IOउत्पादन होता है:

Table 'T'. Scan count 1, logical reads 1011, physical reads 0, read-ahead reads 0
Table 'T'. Scan count 1, logical reads 1001, physical reads 0, read-ahead reads 0
Table 'T'. Scan count 1, logical reads 516, physical reads 0, read-ahead reads 0
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.