सूचकांक अधिकतम पंक्ति आकार त्रुटि


12

क्या एक arrayस्तंभ के लिए एक ऊपरी बाध्य है ?

सरणी फ़ील्ड में सम्मिलित करते समय मुझे यह त्रुटि मिल रही है -

PG::Error: ERROR:  index row size 3480 exceeds maximum 2712 for index "ix_data"

यहाँ मेरी तालिका परिभाषा है -

create table test_array(id varchar(50), data text[]);

ALTER TABLE test_array ADD PRIMARY KEY (id);

CREATE INDEX ix_data ON test_array USING GIN (data);

मुझे सरणी फ़ील्ड पर एक इंडेक्स की आवश्यकता है, क्योंकि मैं उस पर कुछ लुकअप कर रहा हूं।


क्या ऐसा हो सकता है कि स्कॉट स्नाइडर द्वारा संबंधित ब्लॉग पोस्टdata में प्रदर्शित टैग की सूची शामिल हो ? अगर ऐसा है, तो मेरे पास आपके लिए बेहतर समाधान हो सकता है।
एरविन ब्रान्डस्टैटर

user310525, मैं दूसरे इरविन का सुझाव देना चाहूंगा कि यह dba.se पर बेहतर होगा, यदि आप वहां एक खाता बनाने के लिए तैयार हैं और एक मध्यस्थ के लिए फ्लैग करने के लिए झंडा है?
जैक का कहना है कि topanswers.xyz

जवाबों:


14

समस्या

यहाँ 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, जो अतिरिक्त ऑपरेटरों और ऑपरेटर वर्गों की आपूर्ति करता है।

Sqlfiddle पर पूरी तरह कार्यात्मक लाइव डेमो।


2

त्रुटि सूचकांक के साथ है ix_data, न कि text[]क्षेत्र के साथ। विशेष सूचकांक प्रकार में एक पंक्ति के लिए अधिकतम आकार 2712बाइट्स तक सीमित है । यदि आप अपना इंडेक्स ड्रॉप करते हैं और फिर से डालने की कोशिश करते हैं, तो यह आपके लिए काम करना चाहिए। यदि आपको किसी बड़े क्षेत्र को अनुक्रमित करने की आवश्यकता है, तो आप पोस्टग्रेज के पूर्ण पाठ अनुक्रमण सुविधाओं पर गौर करना चाहते हैं।


2

मुझे यह एक PostGIS भूगोल कॉलम पर मिल रहा था। ऐसा इसलिए था क्योंकि मैंने गलती से इंडेक्स को गलत तरीके से बनाया था। ऐसे इंडेक्स बनाते समय आपको USING GIST पैरामीटर को शामिल करना चाहिए।


धन्यवाद - यही था! वाह, अब तक मिला। मुझे घंटों बचाया जा सकता है। खासकर जब से मुझे लगा कि डिफ़ॉल्ट रूप से GiST का उपयोग किया गया था, लेकिन मुझसे गलती हुई और यह बी-ट्री का उपयोग करने की कोशिश करता है।
जोनास
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.