SQL सर्वर में पृष्ठ पर अंक लगाना


17

मेरे पास एक बहुत बड़ा डेटाबेस है, लगभग 100 जीबी। मैं क्वेरी निष्पादित कर रहा हूं:

select * from <table_name>;

और मैं केवल 100 वीं से 200 वीं पंक्तियों को दिखाना चाहता हूं।

मैं समझना चाहता हूं कि यह आंतरिक रूप से कैसे होता है। क्या डेटाबेस डिस्क से मेमोरी में सभी रिकॉर्ड प्राप्त करता है और क्वेरी क्लाइंट को 100 वीं से 400 वीं पंक्तियों को वापस भेजता है? या क्या कोई तंत्र मौजूद है, ताकि केवल उन अभिलेखों (100 वें -200 वें) को डेटाबेस से प्राप्त किया जाए - बी-पेड़ों आदि जैसे अनुक्रमण तंत्र का उपयोग करके?

मैंने पाया कि यह पृष्ठांकन अवधारणा से संबंधित है, लेकिन मैं बिल्कुल नहीं पा सका कि यह डेटाबेस स्तर पर आंतरिक रूप से कैसे होता है।

जवाबों:


37

आपके द्वारा पोस्ट की गई क्वेरी में:

select * from <table_name>;

100 वीं -200 वीं पंक्तियों में ऐसी कोई बात नहीं है, क्योंकि आप ORDER BY को निर्दिष्ट नहीं करते हैं। आदेश की गारंटी नहीं है जब तक कि आप पूरे दिलचस्प कारणों से ORDER BY को शामिल न करें, लेकिन यह वास्तव में यहाँ बात नहीं है।

तो अपनी बात को स्पष्ट करने के लिए, आइए एक तालिका का उपयोग करें - मैं स्टैक ओवरफ्लो डेटा डंप और इस क्वेरी से उपयोगकर्ता तालिका का उपयोग करने जा रहा हूं :

SELECT * FROM dbo.Users ORDER BY DisplayName;

डिफ़ॉल्ट रूप से, DisplayName फ़ील्ड पर कोई इंडेक्स नहीं है, इसलिए SQL सर्वर को संपूर्ण तालिका को स्कैन करना है, फिर इसे DisplayName द्वारा सॉर्ट करें। यहाँ निष्पादन योजना है :

एक सॉर्ट के साथ क्लस्टर इंडेक्स स्कैन

यह सुंदर नहीं है - यह बहुत काम है, लगभग 30k की अनुमानित सबट्री लागत के साथ। (आप इसे PasteThePlan पर चुनिंदा ऑपरेटर पर अपने माउस को मँडरा कर देख सकते हैं।) तो क्या होगा यदि हम केवल 100-200 पंक्तियों को चाहते हैं? हम SQL Server 2012 में इस सिंटैक्स का उपयोग कर सकते हैं:

SELECT * FROM dbo.Users ORDER BY DisplayName OFFSET 100 ROWS FETCH NEXT 100 ROWS ONLY;

उस पर निष्पादन योजना बहुत बदसूरत है:

एक प्रकार और एक शीर्ष के साथ संकुल सूचकांक स्कैन

SQL सर्वर अभी भी आपकी तालिका को 100-200 देने के लिए पूरी सूची को बनाने के लिए पूरी तालिका को स्कैन कर रहा है, और लागत अभी भी 30k के आसपास है। इससे भी बदतर, यह पूरी सूची आपकी क्वेरी चलने पर हर बार फिर से बनाई जाएगी (क्योंकि आखिरकार, किसी ने अपना DisplayName बदल दिया होगा।)

इसे तेज़ी से आगे बढ़ाने के लिए, हम DisplayName पर एक गैर-अनुक्रमित सूचकांक बना सकते हैं, जो कि हमारी तालिका की एक प्रति है, जो उस विशिष्ट क्षेत्र द्वारा क्रमबद्ध है:

CREATE INDEX IX_DisplayName ON dbo.Users(DisplayName);

उस सूचकांक के साथ, हमारी क्वेरी के निष्पादन की योजना अब एक सूचकांक की तलाश करती है:

सूचकांक की तलाश और कुंजी की तलाश

क्वेरी तुरंत समाप्त हो जाती है और इसकी अनुमानित सबट्री लागत केवल 0.66 होती है (30k के विपरीत)।

सारांश में, यदि आप डेटा को उस तरीके से व्यवस्थित करते हैं जो आपके द्वारा चलाए जा रहे प्रश्नों का समर्थन करता है, तो हाँ, SQL सर्वर आपके प्रश्नों को तेज़ी से आगे बढ़ाने के लिए शॉर्टकट ले सकता है। यदि, दूसरी ओर, आपके पास सभी ढेर या क्लस्टर इंडेक्स हैं, तो आप खराब हैं।


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

आपके उत्तर से, मैं समझता हूं कि यदि फ़ील्ड अनुक्रमित है, तो प्रश्न बनाना जैसे - 100 वीं से 200 वीं पंक्ति प्राप्त करना बहुत ही कुशल है क्योंकि एसक्यूएल इंडेक्स (बी-ट्री आदि) तक दिखता है और सीधे उस बिंदु (100 वीं पंक्ति) पर जाता है। क्या आप मुझे बता सकते हैं कि क्या यह सही समझ है?
AV94

@AnilVedala आपके पहले प्रश्न के बारे में - हां, डेटा को सॉर्ट करना होगा। एक डेटाबेस एक और सूची के साथ कैसे पूरा कर सकता है?
ब्रेंट ओजर

1
। आपके दूसरे प्रश्न के बारे में @AnilVedala - (। आप कैसे, एक कार्य योजना लागू करके पढ़ अनुदान Fritchey द्वारा पुस्तक निष्पादन योजनाओं को लेने के लिए के बारे में पूछ रहे हैं) है कि जहां पिछले कार्य योजना लागू करके मैं तुम्हें दे दी है में आता है
ब्रेंट Ozar

15

ब्रेंट के उत्तर के अतिरिक्त, जब एक प्रकार से बचने के लिए नॉन कवरिंग इंडेक्स का उपयोग करते हुए बाद के पृष्ठ संख्याओं के साथ एक संभावित समस्या होती है जिसे नीचे चलाने से देखा जा सकता है

SELECT * 
FROM dbo.Users 
ORDER BY DisplayName 
OFFSET 100000 ROWS 
FETCH NEXT 100 ROWS ONLY;

निष्पादन योजना से पता चलता है कि लुकअप को 100,100 बार निष्पादित किया गया था, भले ही सभी 100 पंक्तियों को फिर TOP ऑपरेटर द्वारा फ़िल्टर किया गया हो।

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

नीचे दिए गए पैटर्न का उपयोग करके इसे कम किया जा सकता है

WITH T
     AS (SELECT Id,
                DisplayName
         FROM   dbo.Users
         ORDER  BY DisplayName
        OFFSET 100000 ROWS 
        FETCH NEXT 100 ROWS ONLY
        )
SELECT U.*
FROM   dbo.Users U
       JOIN T
         ON U.Id = T.Id
ORDER  BY T.DisplayName 

यह लुकअप करने से पहले अंतिम 100 पंक्तियों को छोड़कर सभी फ़िल्टर करता है जो बड़े ऑफसेट मूल्यों के लिए गति पर महत्वपूर्ण प्रभाव डाल सकता है।

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


3

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

यहाँ SQL प्रदर्शन पर एक बहुत अच्छा लेख है जो पृष्ठांकन के विभिन्न तरीकों के बारे में विस्तार से बताता है और वे क्वेरी योजना को कैसे प्रभावित करते हैं। मैं इसे पढ़ने की अत्यधिक सलाह दूंगा और फिर उनमें से कुछ तरीकों को आज़माकर देखूंगा कि आपके अपने सिस्टम पर कौन सी क्वेरी योजना चुनी गई है।

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