सरणियों के कुशल विलय (डुप्लिकेट को हटाने)


10

मेरे पास दो टेबल हैं, left2और right2। दोनों टेबल बड़ी (1-10M पंक्तियाँ) होंगी।

CREATE TABLE left2(id INTEGER, t1 INTEGER, d INTEGER);
ALTER TABLE left2 ADD PRIMARY KEY (id,t1);

CREATE TABLE right2( t1 INTEGER, d INTEGER, arr INTEGER[] );
ALTER TABLE right2 ADD PRIMARY KEY(t1,d);

मैं इस प्रकार की क्वेरी करूँगा:

SELECT l.d + r.d,
       UNIQ(SORT((array_agg_mult(r.arr)))
FROM left2 l,
     right2 r
WHERE l.t1 = r.t1
GROUP BY l.d + r.d
ORDER BY l.d + r.d;

जहां मैं सारणियों के एकत्रीकरण के लिए फ़ंक्शन का उपयोग करता हूं:

CREATE AGGREGATE array_agg_mult(anyarray) (
SFUNC=array_cat,
STYPE=anyarray,
INITCOND='{}');

सरणियों को व्यवस्थित करने के बाद, मैं मॉड्यूल के UNIQफ़ंक्शन का उपयोग करता हूं intarray। क्या ऐसा करने का अधिक कुशल तरीका है? क्या arrविलय को गति देने के लिए क्षेत्र में कोई सूचकांक है (डुप्लिकेट को हटाने के साथ)? क्या कुल फ़ंक्शन सीधे डुप्लिकेट को हटा सकता है? मूल सरणियों को क्रमबद्ध माना जा सकता है (और वे अद्वितीय हैं) यदि यह मदद करता है।

SQL फिडेल यहाँ है :


क्या आप एक बार में लाखों पंक्तियों की क्वेरी करने जा रहे हैं? आप परिणाम के साथ क्या कर रहे हैं? या कुछ का चयन करने के लिए विधेय होगा? क्या right2.arr आपके डेमो स्कीमा की तरह NULL हो सकता है? क्या आपको परिणाम के रूप में क्रमबद्ध सरणियों की आवश्यकता है?
एरविन ब्रान्डेसटेटर

जवाबों:


9

सही परिणाम?

सबसे पहले: शुद्धता। आप अद्वितीय तत्वों की एक सरणी का उत्पादन करना चाहते हैं? आपकी वर्तमान क्वेरी ऐसा नहीं करती है। इन्ट्रेयर मॉड्यूलuniq() से फ़ंक्शन केवल वादे करता है:

आसन्न डुप्लिकेट निकालें

मैनुअल में दिए गए निर्देशों की तरह , आपको इसकी आवश्यकता होगी:

SELECT l.d + r.d, uniq(sort(array_agg_mult(r.arr)))
FROM   ...

साथ ही आपको हल किए गए ऐरे देता है - यह मानते हुए कि आप चाहते हैं, आपने स्पष्ट नहीं किया।

मुझे लगता है कि आपके पास sort() आपकी फिडेल है , इसलिए यह आपके प्रश्न में एक टाइपो हो सकता है।

पोस्टगर्ल्स 9.5

किसी भी तरह से, आप नए Postgres 9.5 (वर्तमान में बीटा) से प्यार करेंगे । यह array_agg_mult()बॉक्स से बाहर की क्षमता प्रदान करता है और बहुत तेजी से:

सरणी हैंडलिंग के लिए अन्य प्रदर्शन सुधार भी हुए हैं।

सवाल

इसका मुख्य उद्देश्य array_agg_mult()बहु-आयामी सरणियों को एकत्रित करना है, लेकिन आप केवल 1-आयामी सरणियों का उत्पादन करते हैं। इसलिए मैं कम से कम इस वैकल्पिक प्रश्न की कोशिश करूंगा:

SELECT l.d + r.d AS d_sum, array_agg(DISTINCT elem) AS result_arr
FROM   left2  l
JOIN   right2 r USING (t1)
     , unnest(r.arr) elem
GROUP  BY 1
ORDER  BY 1;

जो आपके प्रश्न को भी संबोधित करता है:

क्या कुल फ़ंक्शन सीधे डुप्लिकेट को हटा सकता है?

हाँ, यह कर सकते हैं, के साथ DISTINCT। लेकिन यह uniq()पूर्णांक सरणियों से अधिक तेज़ नहीं है , जिसे पूर्णांक सरणियों के लिए अनुकूलित किया गया है, जबकि DISTINCTसभी योग्य डेटा प्रकारों के लिए सामान्य है।

intarrayमॉड्यूल की आवश्यकता नहीं है हालांकि , परिणाम आवश्यक रूप से सॉर्ट नहीं किया गया है। Postgres DISTINCT(IIRC) के लिए अलग-अलग एल्गोरिदम का उपयोग करता है , बड़े सेट आमतौर पर हैशेड होते हैं, फिर परिणाम तब तक सॉर्ट नहीं किया जाता है जब तक आप स्पष्ट नहीं जोड़ते हैं ORDER BY। यदि आपको हल किए गए सरणियों की आवश्यकता है, तो आप सीधे कुल कार्य में जोड़ सकते हैं ORDER BY:

array_agg(DISTINCT elem ORDER BY elem)

लेकिन यह आमतौर पर पूर्व-सॉर्ट किए गए डेटा (एक बड़े सॉर्ट बनाम कई छोटे प्रकार) को खिलाने की तुलना में धीमा है array_agg()। इसलिए मैं एक उप-क्षेत्र में और फिर समग्र करना चाहूंगा :

SELECT d_sum, uniq(array_agg(elem)) AS result_arr
FROM  (
   SELECT l.d + r.d AS d_sum, elem
   FROM   left2  l
   JOIN   right2 r USING (t1)
        , unnest(r.arr) elem
   ORDER  BY 1, 2
   ) sub
GROUP  BY 1
ORDER  BY 1;

Postgres 9.4 पर मेरे सरसरी परीक्षण में यह सबसे तेज़ संस्करण था।

एसक्यूएल फिडल आपके द्वारा प्रदत्त एक के आधार पर।

सूची

मुझे यहां किसी भी सूचकांक के लिए ज्यादा संभावनाएं नहीं दिख रही हैं। एकमात्र विकल्प होगा:

CREATE INDEX ON right2 (t1, arr);

केवल तभी समझ में आता है जब आपको इसमें से केवल-इंडेक्स स्कैन मिलते हैं - जो तब होगा जब अंतर्निहित तालिका right2केवल इन दो स्तंभों की तुलना में व्यापक रूप से व्यापक हो और आपका सेटअप केवल-केवल स्कैन के लिए योग्य हो । पोस्टग्रैज विकी में विवरण।


धन्यवाद +1। मुझे वैसे भी बाद में UNNEST करना होगा, लेकिन अगर सरणियों में डुप्लिकेट को हटा रहा है और फिर UNNEST तेज है, तो यह देखना चाहते हैं।
अलेक्जेंड्रोस

0

मैं वास्तव में निराश हूं, यह माइक्रोसॉफ्ट एक्सेस में एक आसान बात है। आप "डुप्लिकेट हटाएं" क्वेरी बना सकते हैं फिर SQL को देखें कि यह कैसे कर रहा है। मुझे देखने के लिए विंडोज मशीन को फायर करना होगा। वे भिन्न होते हैं, क्वेरी विज़ार्ड इसे करता है।

एक चीज जो मुझे लगता है कि काम करती है, वह है कि आप अपने सभी डेटा को एक तालिका में लोड करें और फिर एक नई तालिका में चयन करें। जब आप उस पर हों, तब आप खंड द्वारा एक क्रम में भी चिपक सकते हैं। मैंने इसे किसी तरह एक साल पहले किया था, यह होना चाहिए।

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

यदि डेटा पूरी तरह से पूरे रन पर एक ही प्रारूप है, तो यूनिक्स मशीन पर आप कुछ ऐसा कर सकते हैं

cat *.tab > points.txt
sort -n < points.txt > sorted.txt
uniq -u sorted.txt unique.txt

लेकिन यूनीक लाइनों की तुलना तार के रूप में करता है और उदाहरण के लिए 18.7000 18.7 के समान नहीं है। मैंने 2 वर्षों के दौरान अपना सॉफ़्टवेयर बदल दिया है इसलिए मेरे पास दोनों प्रारूप हैं।


Postgres से निराश? क्या एक्सेस में भी सरणियाँ हैं?
ypercube y

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