मान NULL के साथ बूलियन के खिलाफ क्वेरी करते समय अनपेक्षित Seq स्कैन


10

मेरे पास एक डेटाबेस कॉलम है जिसे auto_reviewकॉलम प्रकार कहा जाता है boolean। ActiveRecord ORM का उपयोग करके बनाए गए उस फ़ील्ड के लिए एक इंडेक्स है।

CREATE INDEX index_table_on_auto_renew ON table USING btree (auto_renew);

जब मैं बूलियन मान के लिए फ़ील्ड को क्वेरी करता हूं, तो पीजी इंडेक्स का उपयोग अपेक्षित रूप से करता है।

EXPLAIN for: SELECT "table".* FROM "table"  WHERE "table"."auto_renew" = 'f'
                                          QUERY PLAN
----------------------------------------------------------------------------------------------
 Bitmap Heap Scan on table  (cost=51.65..826.50 rows=28039 width=186)
   Filter: (NOT auto_renew)
   ->  Bitmap Index Scan on index_domains_on_auto_renew  (cost=0.00..44.64 rows=2185 width=0)
         Index Cond: (auto_renew = false)
(4 rows)

जब मूल्य होता है NULL, तो एक अनुक्रमिक स्कैन का उपयोग किया जाता है।

EXPLAIN for: SELECT "table".* FROM "table"  WHERE "table"."auto_renew" IS NULL
                           QUERY PLAN
----------------------------------------------------------------
 Seq Scan on table  (cost=0.00..1094.01 rows=25854 width=186)
   Filter: (auto_renew IS NULL)
(2 rows)

मैं इस पसंद के पीछे का कारण जानने के लिए उत्सुक हूं।

जवाबों:


19

आम तौर पर, col IS NULLएक (डिफ़ॉल्ट) बी-ट्री इंडेक्स खोज के लिए एक संभावित उम्मीदवार है। मैनुअल :

इसके अलावा, इंडेक्स कॉलम पर एक IS NULLया IS NOT NULLशर्त का उपयोग बी-ट्री इंडेक्स के साथ किया जा सकता है।

प्रमाण पाने के लिए, अनुक्रमिक स्कैन अक्षम करें (केवल एक परीक्षण सत्र में!):

SET enable_seqscan = OFF;

मैं मैनुअल यहाँ उद्धृत करता हूँ :

enable_seqscan (boolean)

अनुक्रमिक स्कैन योजना प्रकारों के क्वेरी प्लानर के उपयोग को सक्षम या अक्षम करता है। पूरी तरह से अनुक्रमिक स्कैन को दबाने के लिए असंभव है, लेकिन इस चर को बंद करने से योजनाकार को एक का उपयोग करने से हतोत्साहित किया जाता है यदि अन्य तरीके उपलब्ध हैं। डिफ़ॉल्ट चालू है।

फिर पुन: प्रयास करें:

EXPLAIN ANALYZE SELECT * FROM tbl WHERE auto_renew IS NULL;

यह संभवतः बिटमैप इंडेक्स स्कैन के परिणामस्वरूप होगा जो तालिका पर अनुक्रमिक स्कैन की तुलना में धीमा है।

सत्र रीसेट करें या बंद करें (सेटिंग सत्र-स्थानीय है)।

RESET enable_seqscan;

booleanस्तंभों पर अनुक्रमणिका केवल कुछ मामलों में उपयोगी होती हैं। प्लानर केवल एक इंडेक्स का उपयोग करता है यदि यह उम्मीद करता है कि यह तेज हो। गणना आपकी लागत सेटिंग्स और इकट्ठा किए गए आंकड़ों पर आधारित होती है ANALYZE। यदि तालिका का एक बड़ा हिस्सा आपकी स्थिति से मेल खाता है (लगभग 5% या अधिक, यह निर्भर करता है), तो इसके बजाय पूर्ण रूप से पूर्ण स्कैन करना आमतौर पर तेज़ होता है।

यह एक सादे इंडेक्स के लिए एकमात्र उपयोगी उम्मीदवार के रूप में एक कॉलम में दुर्लभ मूल्य को छोड़ देता है boolean। और इसके लिए आम तौर पर इसके बजाय (अधिक विशिष्ट) आंशिक सूचकांक बनाने के लिए अधिक कुशल है - जो क्वेरी स्थिति से मेल खाने के लिए बनाए रखने के लिए सस्ता, छोटा, तेज और अधिक आसानी से उपयोग किया जाता है।

यदि आपके पास पंक्तियों की तलाश में बहुत सारे प्रश्न हैं auto_renew IS NULLऔर NULLमामला बहुत सामान्य नहीं है (और / या आपको एक निश्चित क्रम की आवश्यकता है) तो यह सूचकांक जल्दी से इन पंक्तियों को खोजने / छाँटने में मदद करेगा:

CREATE INDEX index_tbl_tbl_id_auto_renew_null ON tbl (tbl_id)
WHERE auto_renew IS NULL;

आंशिक इंडेक्स की स्थिति WHEREको क्वेरी प्लानर के खंड में दोहराया जाना चाहिए ताकि क्वेरी प्लानर को यह पता चल सके कि सूचकांक लागू है।

अनुक्रमित स्तंभ ( tbl_id) एक मनमाना पिक है। महत्वपूर्ण हिस्सा WHEREक्लॉज है। यह विशेष अनुक्रमणिका ORDER BY tbl_idअतिरिक्त फ़िल्टर के साथ या जुड़ने वाले प्रश्नों के लिए सबसे प्रभावी होगी tbl_id। आप इसे एक बहुरंगी सूचकांक बना सकते हैं । बूलियन कॉलम अक्सर दूसरों के साथ संयोजन में अधिक उपयोगी होते हैं।

एक तरफ: ORM बैसाखी हैं जो नियमित रूप से आपके RDBMS से पूरी क्षमता प्राप्त करने में विफल रहते हैं।


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