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


10

मैं इस पुस्तक को पढ़ रहा हूँ जो कहती है कि

डेटाबेस मानता है कि Indexed_Col नहीं है NULL उपयोगी होने के लिए बहुत बड़ी सीमा को कवर करता है, इसलिए डेटाबेस इस स्थिति से एक इंडेक्स पर ड्राइव नहीं करेगा।

मैं मानता हूं कि पुस्तक 10 साल से अधिक पुरानी है, लेकिन यह पहले से ही काफी उपयोगी साबित हो गई है - इसके पृष्ठों से प्राप्त निर्देशों का उपयोग करते हुए, मैंने दस के एक कारक द्वारा एक क्वेरी तैयार की है।

इसके अलावा, EXPLAIN ANALYZEएक SELECTक्वेरी पर चलने में , मैंने पाया है कि मेरे किसी भी इंडेक्स का उपयोग नहीं किया जा रहा है, यहां तक ​​कि जब सभी अधिकारों द्वारा, वे होना चाहिए।

इस प्रकार, मेरा प्रश्न है:

मान लीजिए कि एक तालिका है जिसमें एक कॉलम है, जिसकी कॉलम परिभाषा में "NOT NULL" शामिल है, और यह कि एक सूचकांक मौजूद है जो इस कॉलम को कवर करता है, तो क्या इस इंडेक्स का उपयोग उस तालिका की क्वेरी में किया जाएगा जहां कॉलम क्वेरी का हिस्सा है?

पसंद:

CREATE TABLE my_table(
a varchar NOT NULL
);

CREATE INDEX ix_my_table ON my_table(a);

SELECT a from my_table;

जवाबों:


9

PostgreSQL निश्चित रूप से के लिए एक सूचकांक का उपयोग कर सकते हैं IS NOT NULL। मैं उस स्थिति के बारे में किसी भी क्वेरी योजनाकार मान्यताओं को नहीं देखता।

यदि स्तंभ के लिए शून्य अंश ( pg_statistic.stanullfrac) यह बताने के लिए पर्याप्त है कि सूचकांक क्वेरी के लिए उपयोगी रूप से चयनात्मक है, तो PostgreSQL एक सूचकांक का उपयोग करेगा।

मैं यह पता नहीं लगा सकता कि आप क्या कहना चाह रहे हैं:

अगर यह सही है, तो क्या मेरी समझ यह है कि "NOT NULL" के रूप में परिभाषित कॉलम पर एक इंडेक्स का उपयोग उस क्वेरी में नहीं किया जाएगा जो उस कॉलम का उपयोग करता है?

निश्चित रूप से एक सूचकांक IS NOT NULLएक NOT NULLस्तंभ पर एक शर्त के लिए इस्तेमाल नहीं किया जाएगा । यह हमेशा 100% पंक्तियों से मेल खाता है, इसलिए एक seqscan लगभग हमेशा बहुत तेज होगा।

यदि इंडेक्स किसी क्वेरी के लिए बड़ी संख्या में पंक्तियों को फ़िल्टर नहीं करता है तो PostgreSQL एक इंडेक्स का उपयोग नहीं करेगा। एकमात्र संभावित अपवाद तब होता है जब आप किसी एकल सूचकांक द्वारा कवर किए गए स्तंभों के एक सेट के लिए पूछ रहे होते हैं, जो कि सूचकांक से मेल खाते हैं। PostgreSQL एक इंडेक्स-केवल स्कैन कर सकता है। उदाहरण के लिए, यदि कोई सूचकांक है t(a, b, c)और आप:

select a, b FROM t ORDER BY a, b, c;

PostgreSQL आपके इंडेक्स का उपयोग कर सकता है, भले ही कोई पंक्तियों को फ़िल्टर न किया गया हो, क्योंकि इसमें केवल इंडेक्स को पढ़ना है और हीप को पढ़ना छोड़ सकते हैं, एक तरह से करने से बचें, आदि।


यह PG 9.0
eradman

1
और यहां तक ​​कि एक अशक्त स्तंभ पर, स्थिति के साथ एक क्वेरी WHERE column IS NOT NULLइंडेक्स का उपयोग नहीं कर सकती है, क्योंकि पुस्तक कहती है: "उपयोगी होने के लिए बहुत बड़ी रेंज शामिल है,"। यदि 90% मान शून्य नहीं हैं, तो एक seqscan शायद तेज भी होगा।
ypercube y

बिल्कुल सही। यह हो सकता है, लेकिन केवल अगर तालिका का एक बड़ा हिस्सा शून्य है। अक्सर इस मामले में एक आंशिक सूचकांक वैसे भी एक बेहतर विकल्प है।
क्रेग रिंगर

हाँ। मैं यह कहने की कोशिश कर रहा था कि (जैसा कि मैं इसे समझता हूं) भाग "बड़ी सीमा को कवर करता है " सूचकांक को संदर्भित करता है लेकिन विशिष्ट स्थिति के संबंध में और सामान्य रूप से सूचकांक नहीं।
ypercube y

2
@FuriousFolder हेह, यहां बहुत अधिक नकारात्मक हैं। PostgreSQL NOT NULLकिसी IS NOT NULLक्वेरी के लिए किसी स्तंभ पर अनुक्रमणिका का उपयोग नहीं करेगा, जब तक कि अनुक्रमणिका WHEREखंड के अन्य भागों के लिए भी उपयोगी न हो, फ़िल्टर इत्यादि में शामिल हो, या एक आदेशित सूचकांक-केवल स्कैन के लिए उपयोग करने योग्य हो। दूसरे शब्दों में, यह पूरी तरह IS NOT NULLसे NOT NULLकॉलम पर बेमानी को नजरअंदाज कर देगा और अन्य विवरणों के आधार पर सूचकांक उपयोग के विकल्प बनाएगा। (देखें संपादित करें, फिर से सूचकांक केवल स्कैन)।
क्रेग रिंगर

2

क्रेग के पूरी तरह से जवाब के अलावा, मैं जोड़ना चाहता हूं कि आपके द्वारा संदर्भित पुस्तक का कवर कहता है:

Oracle, DB2 और SQL सर्वर को शामिल करता है

इसलिए मैं विशेष रूप से PostgreSQL पर सलाह का एक बड़ा स्रोत होने पर भरोसा नहीं करूंगा। हर RDBMS आश्चर्यजनक रूप से अलग हो सकता है!

मैं आपके मूल प्रश्न के बारे में थोड़ा भ्रमित हूं, लेकिन यहां एक उदाहरण दिखा रहा है कि पुस्तक का वह भाग 100% सही नहीं है। आगे की उलझन से बचने के लिए, यहां संपूर्ण प्रासंगिक पैराग्राफ है, आप इसे Google पुस्तक खोज में देख सकते हैं ।

डेटाबेस मानता है कि Indexed_Col नहीं है NULL उपयोगी होने के लिए बहुत बड़ी सीमा को कवर करता है, इसलिए डेटाबेस इस स्थिति से एक इंडेक्स पर ड्राइव नहीं करेगा। दुर्लभ मामलों में, किसी भी गैर-मूल्य का होना इतना दुर्लभ है कि सभी संभव नॉनकूल मूल्यों पर एक इंडेक्स रेंज स्कैन फायदेमंद है। ऐसे मामलों में, यदि आप सभी संभावित मूल्यों की सीमा के लिए एक सुरक्षित निचली या ऊपरी सीमा का पता लगा सकते हैं, तो आप पॉजिटिव_ID_Column> -1 या Date_Column> TO_DATE ('0001/01/01') जैसी स्थिति के साथ एक स्कैन को सक्षम कर सकते हैं। , 'YYYY / MM / DD')।

पोस्टग्रैज वास्तव में (निम्नलिखित विवादित मामले में) एक अनुक्रमणिका का उपयोग IS NOT NULLकरके सुझाव की तरह सीमा स्कैन कीचड़ को जोड़ने के बिना प्रश्नों को संतुष्ट करने के लिए उपयोग कर सकते हैं Positive_ID_Column > -1। क्रेग के सवालों पर टिप्पणियों को देखें कि पोस्टग्रेज इस विशेष मामले में इस सूचकांक को क्यों चुन रहे हैं, और आंशिक अनुक्रमित का उपयोग करने के बारे में नोट।

CREATE TABLE bar (a int);
INSERT INTO bar (a) SELECT NULL FROM generate_series(1,1000000);
INSERT INTO bar (a) VALUES (1);
CREATE INDEX bar_idx ON bar (a);

EXPLAIN ANALYZE SELECT * FROM bar WHERE a IS NOT NULL;
                                                QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 Index Only Scan using bar_idx on bar  (cost=0.42..8.44 rows=1 width=4) (actual time=0.094..0.095 rows=1 loops=1)
   Index Cond: (a IS NOT NULL)
   Heap Fetches: 1
 Total runtime: 0.126 ms
(4 rows)

यह वैसे तो 9.3 पोस्टग्रैज है, लेकिन मेरा मानना ​​है कि परिणाम लगभग 9.1 पर समान होगा, हालांकि यह "इंडेक्स स्कैन" का उपयोग नहीं करेगा।

संपादित करें: मैं देख रहा हूं कि आपने अपने मूल प्रश्न को स्पष्ट कर दिया है, और आप स्पष्ट रूप से सोच रहे हैं कि पोस्टग्रेज एक इंडेक्स का उपयोग सरल उदाहरण में क्यों नहीं कर रहा है:

CREATE TABLE my_table(
a varchar NOT NULL
);

CREATE INDEX ix_my_table ON my_table(a);

SELECT a from my_table;

संभवतः क्योंकि आपके पास तालिका में कोई पंक्तियाँ नहीं हैं। तो कुछ परीक्षण डेटा जोड़ें और ANALYZE my_table;


उक्त पुस्तक (जोर मेरा) के वर्णन में: "लेखक डैन टो एक उत्कृष्ट पद्धति की रूपरेखा प्रस्तुत करता है जिसे वह इष्टतम निष्पादन योजना खोजने के लिए विकसित करता है - तेजी से और व्यवस्थित रूप से - SQL या डेटाबेस प्लेटफ़ॉर्म की जटिलता की परवाह किए बिना ", शायद आपने प्रश्न के # 1 की अनदेखी की है, अर्थात्, कॉलम को इस रूप में परिभाषित किया गया है NOT NULL, न कि यह कि क्वेरी IS NOT NULLइसके सूचकांक स्थिति के रूप में उपयोग करता है । यह आपके द्वारा संदर्भित टिप्पणियों में है, लेकिन मैं इसे शामिल करने के लिए प्रश्न को अपडेट करूंगा।
फ्यूरियस फोल्डर

इसके अलावा, पुस्तक स्वयं भाषा अज्ञेय है: केवल डीएमबीएस-विशिष्ट भाग क्वेरी योजनाओं को दिखाने के बारे में हैं, जो पोस्टग्रैज काफी सरल बनाता है :)
फ्यूरियसफॉल्डर

1
@FuriousFolder कॉलम को NULL के रूप में परिभाषित नहीं किया गया है, लेकिन यह हिस्सा (आपके प्रश्न में, पुस्तक से): "कि Indexed_Col IS NULL कवर नहीं है ..." जहां की स्थिति और कॉलम की परिभाषा नहीं है। हालांकि यह सुनिश्चित होना मुश्किल है, क्योंकि यह संदर्भ से बाहर है। शायद आपको पुस्तक में पूरे (पूर्ववर्ती) पैराग्राफ को शामिल करना चाहिए।
ypercube y

-1

आपने अपनी क्वेरी या उदाहरण डेटा पोस्ट नहीं किया है। लेकिन सबसे आम कारण अनुक्रमित नहीं किया जाता है मात्रा के साथ क्या करना है।

इंडेक्स एक फोनबुक की तरह होते हैं जो एक कॉलम को पंक्ति स्थान पर अनुवादित करता है। यदि आप केवल कुछ पंक्तियों की तलाश कर रहे हैं, तो फोनबुक में प्रत्येक पंक्ति को देखने के लिए समझ में आता है, और फिर मुख्य तालिका में पंक्ति को देखें।

लेकिन कुछ पंक्तियों से अधिक के लिए, फोनबुक को छोड़ना सस्ता है, और मुख्य तालिका में सभी पंक्तियों पर पुनरावृति। मेरे अनुभव में टिपिंग बिंदु लगभग 100 पंक्तियाँ हैं।


"अनुक्रमणिका एक फोनबुक की तरह होती है जो एक पंक्ति स्थान पर एक कॉलम का अनुवाद करती है। यदि आप केवल कुछ पंक्तियों की तलाश कर रहे हैं, तो यह फोनबुक में प्रत्येक पंक्ति को देखने के लिए समझ में आता है, और फिर मुख्य तालिका में पंक्ति को देखें।" दरअसल, इंडेक्स छोटी फोनबुक की तरह होते हैं जिन्हें किसी भी समय अपडेट किया जाता है। आप जानते हैं कि किसी भी समय आप एक छोटी सी फोनबुक खोलते हैं, आप किसी भी और सभी जानकारी को खोजने जा रहे हैं, जो इसकी अनुक्रमण स्थिति का वर्णन करता है। उदाहरण के लिए, सभी लोगों को एक इंडेक्स टेबल पर 'फ्रैंक' नाम दिया गया है CREATE INDEX ix_frank ON people(name) WHERE name ='frank':।
फ्यूरियसफॉल्डर

यह अनुमति देता है एक सूचकांक-केवल होने के लिए स्कैन बहुत ज्यादा जब से तुम स्मृति में पूरी "छोटे फोनबुक" है, जो एक बहु मिलियन लाइन की मेज के साथ संभव नहीं है पढ़ सकते हैं, तेजी से।
फ्यूरियसफॉल्डर

@FuriousFolder: आप केवल एक इंडेक्स-स्कैन का वर्णन कर रहे हैं। लेकिन ओपी का कहना है कि उसके इंडेक्स का उपयोग नहीं किया जा रहा है, जो ऐसा नहीं होगा यदि इंडेक्स-केवल स्कैन क्वेरी को संतुष्ट करेगा।
एंडोमर

Andomar ... मैं कर रहा हूँ ओपी, haha। मेरा लक्ष्य ठीक यही है; सूचकांक-केवल स्कैन का उपयोग करने के लिए इस क्वेरी को प्राप्त करने के लिए। मैंने तब से इसे हासिल किया है, जब से क्रेग ने समझाया कि पोस्टग्रेज एक कॉलम पर एक इंडेक्स का उपयोग करने में सक्षम है, जहां कॉलम की परिभाषा में शामिल है NOT NULL
फ्यूरियसफॉल्गर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.