"बिटमैप हीप स्कैन" और "बिटमैप इंडेक्स स्कैन" को समझना


36

मैं निम्नलिखित उदाहरण द्वारा अपनी गलतफहमी को समझाने की कोशिश करूँगा।

मैं के मूल सिद्धांतों को समझ नहीं पाया Bitmap Heap Scan Node। प्रश्न पर विचार करें कि यह किसकी SELECT customerid, username FROM customers WHERE customerid < 1000 AND username <'user100';योजना है:

Bitmap Heap Scan on customers  (cost=25.76..61.62 rows=10 width=13) (actual time=0.077..0.077 rows=2 loops=1)
  Recheck Cond: (((username)::text < 'user100'::text) AND (customerid < 1000))
  ->  BitmapAnd  (cost=25.76..25.76 rows=10 width=0) (actual time=0.073..0.073 rows=0 loops=1)
        ->  Bitmap Index Scan on ix_cust_username  (cost=0.00..5.75 rows=200 width=0) (actual time=0.006..0.006 rows=2 loops=1)
              Index Cond: ((username)::text < 'user100'::text)
        ->  Bitmap Index Scan on customers_pkey  (cost=0.00..19.75 rows=1000 width=0) (actual time=0.065..0.065 rows=999 loops=1)
              Index Cond: (customerid < 1000)

इस नोड के बारे में मेरी समझ :

जैसा कि वहां बताया गया है , bitmap heap scanक्रमबद्ध क्रम में टेबल ब्लॉक पढ़ता है, इसलिए यह रैंडम-टेबल-एक्सेस ओवरहेड का उत्पादन नहीं करता है जो कि बस करने के रूप में होता है Index Scan

के बाद Index Scanकिया गया है, PostgreSQL पता नहीं कैसे पंक्तियों को लाने के लिए, अनावश्यक रूप से heap blocks reads(या hitsअगर वहाँ एक गर्म कैश है) से बचने के लिए । इसलिए यह पता लगाने के लिए कि यह संरचना ( Bitmap Index Scan) उत्पन्न करता है जिसे कहा जाता है bitmapकि मेरे मामले में सूचकांक के दो बिटमैप उत्पन्न करके और प्रदर्शन किया जा रहा है BITWISE AND। चूंकि बिटमैप उत्पन्न हो गया है, अब अनावश्यक रूप से बचने के लिए, क्रमिक क्रम में तालिका को बेहतर ढंग से पढ़ा जा सकता है heap I/O-operations

यही वह जगह है जहां बहुत सारे सवाल आते हैं।

प्रश्न: हमारे पास बस एक बिटमैप है। कैसे PostgreSQL पंक्तियों के भौतिक क्रम के बारे में कुछ भी नहीं जानता है? या बिटमैप उत्पन्न करता है ताकि इसके किसी भी तत्व को सूचक को एक पृष्ठ पर आसानी से मैप किया जा सके? यदि हां, तो यह सब कुछ समझाता है, लेकिन यह सिर्फ मेरा अनुमान है।

तो, क्या हम केवल इतना कह सकते हैं कि यह bitmap heap scan -> bitmap index scanएक अनुक्रमिक स्कैन की तरह है लेकिन केवल तालिका के उचित भाग की तरह है?


मैंने इसमें से कुछ का स्पष्टीकरण यहां लिखा है: stackoverflow.com/q/33100637/398670
क्रेग रिंगर

@CraigRinger ऐसा लगता है कि मैंने सही ढंग से समझाया नहीं कि मुझे क्या समझ में नहीं आया। बेशक, जैसा कि आपने बताया कि हमारे पास एक बिटमैप है जिसके द्वारा PostgreSQL तालिका को क्रमिक रूप से पढ़ता है। मुझे समझ नहीं आता कि यह एक विशिष्ट बिटमैप द्वारा निर्दिष्ट वास्तविक ब्लॉक का कैसे पता लगा सकता है 001001010101011010101। या यह वास्तव में कोई फर्क नहीं पड़ता है और हम सभी को पता है कि यह काफी तेजी से बिटमैप द्वारा एक ब्लॉक मिल सकता है ...?
सेंटऑनारियो

आह, आप गलत समझ रहे होंगे कि "बिटमैप" का क्या मतलब है। मुझे एक संपादन में फॉलो करें।
क्रेग रिंगर

@ क्रेगिंगर, हो सकता है, मैंने वहाँ से डिफिनिशन लिया हो
सेंटऑनारियो

जवाबों:


52

कैसे PostgreSQL पंक्तियों के भौतिक क्रम के बारे में कुछ भी नहीं जानता है?

बिटमैप एक बिट प्रति ढेर पृष्ठ है। बिटमैप इंडेक्स स्कैन बिट्स को ढेर पृष्ठ पते के आधार पर सेट करता है जो इंडेक्स एंट्री पॉइंट को इंगित करता है।

तो जब यह बिटमैप ढेर स्कैन करने के लिए जाता है, तो यह सिर्फ एक रैखिक तालिका स्कैन करता है, बिटमैप को पढ़ने के लिए यह देखने के लिए कि क्या यह किसी विशेष पृष्ठ से परेशान होना चाहिए या इसे ढूंढना चाहिए।

या बिटमैप उत्पन्न करता है ताकि इसके किसी भी तत्व को सूचक को एक पृष्ठ पर आसानी से मैप किया जा सके?

नहीं, बिटमैप पृष्ठों को ढेर करने के लिए 1: 1 से मेल खाता है।

मैंने इस पर कुछ और लिखा है


ठीक है, ऐसा लगता है कि आप गलत समझ रहे होंगे कि इस संदर्भ में "बिटमैप" का क्या अर्थ है।

यह "101011" जैसा कोई स्ट्रिंग नहीं है जो प्रत्येक हीप पेज, या प्रत्येक इंडेक्स, या जो कुछ भी है, के लिए बनाया गया है।

संपूर्ण बिटमैप एक एकल बिट सरणी है , जिसमें कई बिट्स हैं, जो स्कैन किए गए संबंध में ढेर पृष्ठ हैं।

एक बिटमैप पहले इंडेक्स स्कैन द्वारा बनाया जाता है, जो सभी प्रविष्टियों 0 (गलत) के साथ शुरू होता है। जब भी कोई अनुक्रमणिका प्रविष्टि जो खोज स्थिति से मेल खाती है, तो उस अनुक्रमणिका प्रविष्टि द्वारा इंगित हीप पते को बिटमैप में ऑफसेट के रूप में देखा जाता है, और यह बिट 1 (सच) पर सेट होता है। तो सीधे हीप पेज देखने के बजाय, बिटमैप इंडेक्स स्कैन बिटमैप में संबंधित बिट स्थिति को देखता है।

दूसरा और आगे बिटमैप इंडेक्स स्कैन अन्य इंडेक्स और उन पर खोज स्थितियों के साथ एक ही काम करते हैं।

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

इन सबके साथ एक महत्वपूर्ण बात यह समझने की है कि इंडेक्स एंट्री में टपल एड्रेस पंक्ति का है ctid, जो हीप पेज नंबर और हीप पेज के भीतर ऑफसेट का संयोजन है। बिटमैप इंडेक्स स्कैन ऑफ़सेट को अनदेखा करता है, क्योंकि यह पूरे पृष्ठ को वैसे भी जाँचता है, और बिट सेट करता है यदि उस पृष्ठ पर कोई भी पंक्ति स्थिति से मेल खाती है।


चित्रमय उदाहरण

Heap, one square = one page:
+---------------------------------------------+
|c____u_____X___u___X_________u___cXcc______u_|
+---------------------------------------------+
Rows marked c match customers pkey condition.
Rows marked u match username condition.
Rows marked X match both conditions.


Bitmap scan from customers_pkey:
+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
+---------------------------------------------+
One bit per heap page, in the same order as the heap
Bits 1 when condition matches, 0 if not

Bitmap scan from ix_cust_username:
+---------------------------------------------+
|000001000001000100010000000001000010000000010| bitmap 2
+---------------------------------------------+

एक बार बिटमैप बनने के बाद एक बिटवाइज़ बनाई जाती है और उन पर प्रदर्शन किया जाता है:

+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
|000001000001000100010000000001000010000000010| bitmap 2
 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|000000000001000000010000000000000010000000000| Combined bitmap
+-----------+-------+--------------+----------+
            |       |              |
            v       v              v
Used to scan the heap only for matching pages:
+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+

बिटमैप हीप स्कैन तब प्रत्येक पृष्ठ की शुरुआत चाहता है और पृष्ठ को पढ़ता है:

+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+
seek------->^seek-->^seek--------->^
            |       |              |
            ------------------------
            only these pages read

और प्रत्येक पढ़ा हुआ पृष्ठ फिर से हालत के खिलाफ फिर से जाँच लिया जाता है क्योंकि प्रति पृष्ठ> 1 पंक्ति हो सकती है और सभी जरूरी शर्त से मेल नहीं खाती हैं।


आह, बिटमैप को पॉप्युलेट करने से उनका मतलब है ।
सेंटएंटारियो

@ सेंटऑनारियो मैंने समझाने के लिए ग्राफिक्स जोड़े हैं
क्रेग रिंगर

मुझे बिटमैप-स्कैन के बारे में एक और बात स्पष्ट करनी चाहिए। आपने कहा कि हमारे पास पृष्ठों को छिपाने के लिए 1: 1 बिटमैप है और हम बिटमैप में एक बिट इंडेक्स द्वारा एक हीप पृष्ठ निर्धारित कर सकते हैं। चूंकि संबंध एक क्रमिक क्रम में एक डिस्क पर पृष्ठ हो सकते हैं (गैर संकुल) यह बिल्कुल स्पष्ट नहीं है कि हम किसी बिटमैप में केवल ऑफसेट द्वारा पृष्ठ के पते को कैसे निर्धारित कर सकते हैं। मुझे लगता है, योजनाकार एक दिए गए संबंध के लिए ऑफसेट द्वारा एक पृष्ठ पते की गणना करना जानता है । क्या यह सच है?
सेंटएन्टारियो

1
इसलिए हमें उन सभी पृष्ठों को रखना होगा जो एक ड्राइव पर हैं। इसके अलावा, संबंध का डेटा दो या अधिक ड्राइव पर फैलाया जा सकता है (इसलिए संबंध के पृष्ठों के किसी भी रैखिक क्रम की कल्पना करना मुश्किल है ), इसलिए अगले पृष्ठ की वास्तविक ऑफसेट का निर्धारण करना मुश्किल है। क्योंकि मेरा मानना ​​है कि "ऑफसेट" से आपका तात्पर्य एक ड्राइव पर भौतिक स्थिति के अनुरूप वास्तविक भौतिक ऑफसेट से है।
सेंटअनतारियो

2
PostgreSQL ड्राइव के बारे में थोड़ी सी भी परवाह नहीं करता है। यह केवल फाइल सिस्टम पर फाइलों की परवाह करता हैतार्किक संबंध के लिए फ़ाइल रैखिक और सन्निहित है, और उस की क्या बिटमैप खत्म हो गया है। (फ़ाइल में कई एक्स्टेंट हो सकते हैं, लेकिन उन्हें ऐसा माना जाता है जैसे कि उन्हें लगातार जोड़ा जाता है, और बिटमैप उन सभी से अधिक है)। आप गलत अमूर्त स्तर को देख रहे हैं। (एक साइड नोट पर, बिटमैप इंडेक्स स्कैन में बिटमैप की गणना प्लानर द्वारा नहीं की जाती है, यह btree इंडेक्स एक्सेस विधि का हिस्सा है और प्लानर की तुलना में निष्पादक से अधिक संबंधित है)।
क्रेग रिंगर

3

PostgreSQL में बिटमैप स्कैन के विवरण के लिए कृपया मेरे ब्लॉग पोस्ट को देखें https://rajeevrastogi.blogspot.in/2018/02/bitmap-scan-in-postgresql.html?showComment=1518410565792#c46473576462092142586

बिटमैप स्कैन की कुल त्वरित कार्यक्षमता अवलोकन:

  1. बिटमैप हीप स्कैन बिटमैप इंडेक्स स्कैन से टपल मांगता है।

  2. बिटमैप इंडेक्स स्कैन सामान्य इंडेक्स स्कैन के अनुसार सूचकांक को लगभग उसी तरह से स्कैन करता है। लेकिन TID को वापस करने के बजाय, डेटा को ढेर करने के लिए संबंधित (पृष्ठ संख्या और उस के भीतर ऑफसेट), यह एक बिटमैप में उन TID को जोड़ता है। सरल समझ के लिए, आप इस बिटमैप में सभी पृष्ठों का हैश (पृष्ठ संख्या के आधार पर हैश) और प्रत्येक पृष्ठ प्रविष्टि में उस पृष्ठ के भीतर सभी ऑफ़सेट की सरणी समाहित है पर विचार कर सकते हैं।

  3. तब बिटमैप हीप स्कैन बिटमैप के माध्यम से संग्रहित पृष्ठ संख्या और ऑफ़सेट के लिए हीप डेटा प्राप्त करने के लिए पढ़ता है। फिर यह दृश्यता, योग्यता आदि की जाँच करता है और इन सभी जाँचों के परिणाम के आधार पर टपल लौटाता है।

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