समस्या
यहाँ pgsql.general पर एक बहुत ही समान मामला है । यह एक बी-ट्री इंडेक्स में सीमा के बारे में है, लेकिन यह सब एक ही है क्योंकि जीआईएन इंडेक्स कुंजी के लिए आंतरिक रूप से बी-ट्री इंडेक्स का उपयोग करता है और इसलिए कुंजी आकार ( सादे बी-ट्री में आइटम आकार के बजाय एक ही सीमा में चलता है) इंडेक्स)।
मैं GIN सूचकांक कार्यान्वयन के बारे में मैनुअल उद्धृत करता हूं :
आंतरिक रूप से, GIN इंडेक्स में कुंजियों पर निर्मित B-ट्री इंडेक्स होता है, जहां प्रत्येक कुंजी एक या एक से अधिक इंडेक्स आइटम का एक तत्व होता है
किसी भी तरह से, आपके स्तंभ में कम से कम एक सरणी तत्वdata
अनुक्रमित होने के लिए बहुत बड़ा है। यदि यह सिर्फ एक विलक्षण सनकी मूल्य या किसी प्रकार की दुर्घटना है, तो आप मूल्य को कम कर सकते हैं और इसके साथ किया जा सकता है।
निम्नलिखित डेमो के उद्देश्य के लिए मैं अन्यथा मानूंगा: सरणी में लंबे पाठ मान।
सरल उपाय
आप हैश मान केdata
अनुसार अपने ऐरे में तत्वों को बदल सकते हैं । और उसी हैश फ़ंक्शन के माध्यम से लुक-अप मान भेजें। बेशक, आप शायद इसके अलावा अपने मूल को कहीं और स्टोर करना चाहते हैं। उस के साथ, हम लगभग मेरे दूसरे संस्करण में आते हैं ...
उन्नत समाधान
आप serial
सरोगेट प्राथमिक कुंजी के रूप में एक स्तंभ के साथ सरणी तत्वों के लिए एक लुक-अप तालिका बना सकते हैं (प्रभावी रूप से हैश मान का एक कट्टरपंथी) - जो सभी अधिक दिलचस्प है यदि इसमें शामिल तत्व मान अद्वितीय नहीं हैं:
CREATE TABLE elem (
elem_id serial NOT NULL PRIMARY KEY
, elem text UNIQUE NOT NULL
);
जब से हम को देखने के लिए चाहते हैं elem
-, हम एक सूचकांक जोड़ने लेकिन एक एक अभिव्यक्ति पर सूचकांक के साथ ही इस बार, पहले 10 अक्षर लंबे पाठ की। यह एक या कुछ हिट के लिए एक खोज को कम करने के लिए ज्यादातर मामलों में पर्याप्त होना चाहिए। अपने डेटा वितरण के लिए आकार को अनुकूलित करें। या अधिक परिष्कृत हैश फ़ंक्शन का उपयोग करें।
CREATE INDEX elem_elem_left10_idx ON elem(left(elem,10));
आपका स्तंभ data
तब प्रकार का होगा int[]
। मैंने तालिका का नाम बदलकर आपके उदाहरण में आपके द्वारा किए data
गए अशुभ से छुटकारा पाया varchar(50)
:
CREATE TEMP TABLE data(
data_id serial PRIMARY KEY
, data int[]
);
प्रत्येक सरणी तत्व data
एक को संदर्भित करता है elem.elem_id
। इस बिंदु पर, आप सरणी स्तंभ को n: m तालिका से प्रतिस्थापित करने पर विचार कर सकते हैं, जिससे आपका स्कीमा सामान्य हो जाएगा और Postgres को संदर्भात्मक अखंडता लागू करने की अनुमति मिलेगी। अनुक्रमण और सामान्य हैंडलिंग आसान हो जाती है ...
हालाँकि, प्रदर्शन कारणों से, int[]
GIN इंडेक्स के साथ संयोजन में कॉलम बेहतर हो सकता है। भंडारण का आकार बहुत छोटा है। इस मामले में हमें GIN सूचकांक की आवश्यकता है:
CREATE INDEX data_data_gin_idx ON data USING GIN (data);
अब, GIN सूचकांक (= सरणी तत्व) की प्रत्येक कुंजीinteger
एक लोंगिश के बजाय है text
। सूचकांक परिमाण के कई आदेशों से छोटा होगा, फलस्वरूप खोज बहुत तेज होगी।
नकारात्मक पक्ष: इससे पहले कि आप वास्तव में एक खोज कर सकें आपको elem_id
मेज से देखना होगा elem
। मेरे नए शुरू किए गए कार्यात्मक सूचकांक का उपयोग करना elem_elem_left10_idx
, यह, बहुत तेज होगा।
आप यह सब एक सरल क्वेरी में कर सकते हैं :
SELECT d.*, e.*
FROM elem e
JOIN data d ON ARRAY[e.elem_id] <@ d.data
WHERE left(e.elem, 10) = left('word1234word', 10) -- match index condition
AND e.elem = 'word1234word'; -- need to recheck, functional index is lossy
आप एक्सटेंशन में दिलचस्पी ले सकते हैं intarray
, जो अतिरिक्त ऑपरेटरों और ऑपरेटर वर्गों की आपूर्ति करता है।
data
में प्रदर्शित टैग की सूची शामिल हो ? अगर ऐसा है, तो मेरे पास आपके लिए बेहतर समाधान हो सकता है।