PostgreSQL अनुक्रमित कॉलम पर अनुक्रमिक स्कैन क्यों करता है?


150

बहुत सरल उदाहरण - एक तालिका, एक सूचकांक, एक प्रश्न:

CREATE TABLE book
(
  id bigserial NOT NULL,
  "year" integer,
  -- other columns...
);

CREATE INDEX book_year_idx ON book (year)

EXPLAIN
 SELECT *
   FROM book b
  WHERE b.year > 2009

मुझे देता है:

Seq Scan on book b  (cost=0.00..25663.80 rows=105425 width=622)
  Filter: (year > 2009)

इसके बजाय यह इंडेक्स स्कैन क्यों नहीं करता है? मैं क्या खो रहा हूँ?

जवाबों:


222

यदि तालिका में सभी पंक्तियों के लगभग 5-10% से अधिक का चयन करता है, तो अनुक्रमिक स्कैन एक सूचकांक स्कैन की तुलना में बहुत तेज है।

ऐसा इसलिए है क्योंकि एक सूचकांक स्कैन के लिए प्रत्येक पंक्ति के लिए कई IO संचालन की आवश्यकता होती है (सूचकांक में पंक्ति देखें, फिर हीप से पंक्ति पुनः प्राप्त करें)। जबकि एक अनुक्रमिक स्कैन में केवल प्रत्येक पंक्ति के लिए एक एकल IO की आवश्यकता होती है - या इससे भी कम क्योंकि डिस्क पर एक ब्लॉक (पृष्ठ) में एक से अधिक पंक्ति होती है, इसलिए एक से अधिक पंक्ति को एक एकल IO ऑपरेशन के साथ लाया जा सकता है।

Btw: यह अन्य DBMS के लिए भी सही है - कुछ अनुकूलन को "इंडेक्स केवल स्कैन" के रूप में एक तरफ ले जाया जाता है (लेकिन एक चयन के लिए * यह अत्यधिक संभावना नहीं है कि ऐसा कोई डीबीएमएस "इंडेक्स ओनली स्कैन" के लिए जाएगा)


12
5-10% विन्यास सेटिंग्स और डेटा के भंडारण के एक जोड़े पर निर्भर करता है। यह कोई कठिन संख्या नहीं है।
फ्रैंक हाइकेन

6
@ फ्रेंक: इसीलिए मैंने "लगभग" कहा: :) लेकिन इसे इंगित करने के लिए धन्यवाद
a_horse_with_no_name

5
इसके अलावा, एक अनुक्रमिक स्कैन एक समय में ढेर से कई पेजों का अनुरोध कर सकता है, और कर्नेल को अगला चंक लाने के लिए कह सकता है, जबकि यह वर्तमान एक पर काम करता है- एक इंडेक्स स्कैन एक बार में एक पेज प्राप्त करता है। (एक बिटमैप स्कैन दोनों के बीच एक समझौता करता है, आप आमतौर पर उन प्रश्नों की योजना में दिखाई देते हैं जो एक इंडेक्स स्कैन के लिए पर्याप्त रूप से चयनात्मक नहीं होते हैं, लेकिन फिर भी इतना
अचूक

4
दिलचस्प सवाल यह है कि डेटाबेस कैसे जानता है कि क्वेरी कितनी पंक्तियों को पहले किए बिना वापस आ जाएगी? क्या यह आँकड़ों को स्टोर करता है जैसे कि अलग-अलग मूल्यों की संख्या बनाम टेबल आकार कहीं?
लॉरेंट ग्रेगोइरे

7
@ LaurentGrégoire: हां, डेटाबेस पंक्तियों की संख्या और मूल्यों के वितरण के बारे में आंकड़े संग्रहीत करता है। विवरण के लिए मैनुअल देखें: postgresql.org/docs/current/static/planner-stats.html
a_horse_with_no_name


0

इंडेक्स स्कैन में, हेड जंप को एक पंक्ति से दूसरी पंक्ति में पढ़ा जाता है जो अगले भौतिक ब्लॉक (अनुक्रमिक स्कैन में) पढ़ने की तुलना में 1000 गुना धीमा है।

इसलिए, यदि (१००० प्राप्त करने के लिए रिकॉर्ड की संख्या) रिकॉर्ड की कुल संख्या से कम है, तो सूचकांक स्कैन बेहतर प्रदर्शन करेगा।


0

@a_horse_with_no_name ने इसे अच्छी तरह समझाया। इसके अलावा यदि आप वास्तव में एक इंडेक्स स्कैन का उपयोग करना चाहते हैं, तो आपको आम तौर पर जहां खंड में बंधी हुई सीमाओं का उपयोग करना चाहिए। जैसे - वर्ष> 2019 और वर्ष <2020।

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

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