पोस्टग्रेएसक्यूएल वास्तव में सरणी कॉलम पर जीआईएन इंडेक्स का समर्थन करता है। दुर्भाग्यवश, यह NOT ARRAY[...] <@ indexed_col
के लिए उपयोग करने योग्य प्रतीत नहीं होता है, और GIN
अनुक्रमणिका अक्सर-अद्यतन तालिकाओं के लिए अनुपयुक्त हैं।
डेमो:
CREATE TABLE arrtable (id integer primary key, array_column integer[]);
INSERT INTO arrtable(1, ARRAY[1,2,3,4]);
CREATE INDEX arrtable_arraycolumn_gin_arr_idx
ON arrtable USING GIN(array_column);
-- Use the following *only* for testing whether Pg can use an index
-- Do not use it in production.
SET enable_seqscan = off;
explain (buffers, analyze) select count(id)
from arrtable
where not (ARRAY[1] <@ arrtable.array_column);
दुर्भाग्य से, यह पता चलता है कि के रूप में लिखा हम सूचकांक का उपयोग नहीं कर सकते हैं। यदि आप इस शर्त को अस्वीकार नहीं करते हैं तो इसका उपयोग किया जा सकता है, ताकि आप में खोज तत्व (NOT
को हटाकर) पंक्तियों की खोज और गणना कर सकें।
आप प्रविष्टियों को गिनने के लिए इंडेक्स का उपयोग कर सकते हैं में लक्ष्य मान होता है, फिर उस प्रविष्टि को सभी प्रविष्टियों की गणना से घटाएं। चूंकि count
आईएनजी तालिका में सभी पंक्तियां PostgreSQL (9.1 और पुराने) में काफी धीमी है और अनुक्रमिक स्कैन की आवश्यकता है, यह वास्तव में आपकी वर्तमान क्वेरी से धीमी होगी। यह संभव है कि 9.2 पर एक सूचकांक-केवल स्कैन पंक्तियों गिनती करने के लिए इस्तेमाल किया जा सकता है कि अगर आप id
पर एक बी पेड़ सूचकांक, जिस स्थिति में यह वास्तव में ठीक हो सकता है है:
SELECT (
SELECT count(id) FROM arrtable
) - (
SELECT count(id) FROM arrtable
WHERE (ARRAY[1] <@ arrtable.array_column)
);
यह से भी बदतर प्रदर्शन करने के लिए गारंटी है पीजी 9.1 और उसके बाद के लिए आपका मूल संस्करण, क्योंकि seqscan के अतिरिक्त आपके मूल को भी को एक जीआईएन इंडेक्स स्कैन की आवश्यकता है। मैंने अब 9.2 पर इसका परीक्षण किया है और यह गिनती के लिए एक इंडेक्स का उपयोग करने लगता है, इसलिए 9.2 के लिए खोज करना उचित है।
drop index arrtable_arraycolumn_gin_arr_idx ;
truncate table arrtable;
insert into arrtable (id, array_column)
select s, ARRAY[1,2,s,s*2,s*3,s/2,s/4] FROM generate_series(1,1000000) s;
CREATE INDEX arrtable_arraycolumn_gin_arr_idx
ON arrtable USING GIN(array_column);
ध्यान दें कि इस तरह की एक जिन सूचकांक अपडेट नीचे एक बहुत धीमी हो जाएगी, और काफी पहले स्थान पर बनाने के लिए धीमी है: कुछ कम तुच्छ डमी डेटा के साथ। यह उन टेबलों के लिए उपयुक्त नहीं है जो आपकी तालिका की तरह बहुत अधिक अपडेट हो जाते हैं।
बदतर, इस इंडेक्स का उपयोग करने वाली क्वेरी आपके मूल क्वेरी के रूप में दो गुना तक और उसी डेटा सेट पर तक आधे से अधिक समय तक ले जाती है। यह उन मामलों के लिए सबसे खराब है जहां सूचकांक ARRAY[1]
- 4s बनाम 2s मूल क्वेरी के लिए बहुत चुनिंदा नहीं है। जहां सूचकांक अत्यधिक चुनिंदा है (यानी: ARRAY[199]
जैसे कई मैचों नहीं) यह मूल के 3s बनाम लगभग 1.2 सेकंड में चलता है। यह सूचकांक इस क्वेरी के लिए बस लायक नहीं है।
यहां सबक? कभी-कभी, सही उत्तर केवल अनुक्रमिक स्कैन करना है।
कि चूंकि अपने हिट दरों के लिए करना होगा नहीं, या तो एक ट्रिगर के साथ एक materialized दृश्य को बनाए रखने के @debenhur के रूप में पता चलता है, या सरणी को उलटने के लिए मानकों को प्रवेश करता है कि नहीं तो आप की एक सूची बनने की कोशिश एक जीआईएसटी इंडेक्स का उपयोग @maniek के रूप में कर सकता है।
यकीन नहीं है, लेकिन मुझे लगता है कि table.array_column पर एक जीआईएन इंडेक्स इसे गति देने में मदद करेगा। पता लगाने के लिए आपको एक्स्पलाइन चलाने की आवश्यकता होगी। यहां देखें: http://dba.stackexchange.com/a/27505/1822 –
पोस्टग्रेस में यह कुशल बनाना मुश्किल होगा क्योंकि तालिका बड़ी हो जाती है। एक जीन इंडेक्स केवल तभी मदद करेगा जब "निहित" के परीक्षण के रूप में आपके भविष्य में "निहित नहीं" के विपरीत। यदि यह महत्वपूर्ण नहीं है कि गणना 100% सटीक हो, तो आप इसे कुछ टीटीएल के साथ ऐप परत पर कैशिंग करने का प्रयास कर सकते हैं। यदि तालिका पर आपकी लेखन दर बहुत अधिक नहीं है, तो आप वर्तमान गणना वाले किसी अन्य तालिका को अपडेट करने के लिए ट्रिगर का उपयोग कर सकते हैं। – dbenhur
अपना संस्करण दिखाने के लिए सर्वश्रेष्ठ और 'विश्लेषण की व्याख्या करें'; http://stackoverflow.com/tags/postgresql-performance/info –