दो चीजें:1) आप डेटाबेस का पूरी तरह से उपयोग नहीं कर रहे हैं और 2) आपकी समस्या कस्टम PostgreSQL एक्सटेंशन के लिए एक बेहतरीन उदाहरण है। यही कारण है।
आप केवल डेटाबेस का उपयोग भंडारण के रूप में कर रहे हैं, रंगों को फ्लोट के रूप में संग्रहीत कर रहे हैं। आपके वर्तमान कॉन्फ़िगरेशन में, क्वेरी के प्रकार की परवाह किए बिना, डेटाबेस को हमेशा सभी मानों की जांच करनी होगी (एक अनुक्रमिक स्कैन करें)। इसका मतलब है बहुत सारे आईओ और कुछ लौटे मैचों के लिए बहुत अधिक गणना। आप निकटतम N रंगों को खोजने का प्रयास कर रहे हैं, इसलिए सभी डेटा पर गणना करने से बचने के तरीके के बारे में कुछ संभावनाएं हैं।
साधारण सुधार
अपनी गणनाओं को डेटा के एक छोटे सबसेट तक सीमित करना सबसे आसान है। आप मान सकते हैं कि यदि घटक अधिक भिन्न होते हैं तो अंतर अधिक होगा। यदि आप घटकों के बीच एक सुरक्षित अंतर पा सकते हैं, जहां परिणाम हमेशा अनुपयुक्त होते हैं, तो आप उन रंगों को पूरी तरह से Btree अनुक्रमणिका के साथ WHERE रेंज का उपयोग करके बाहर कर सकते हैं। हालांकि, L*a*b कलरस्पेस की प्रकृति के कारण, यह आपके परिणामों को खराब कर सकता है।
पहले इंडेक्स बनाएं:
CREATE INDEX color_lab_l_btree ON color USING btree (lab_l);
CREATE INDEX color_lab_a_btree ON color USING btree (lab_a);
CREATE INDEX color_lab_b_btree ON color USING btree (lab_b);
फिर मैंने आपकी क्वेरी को केवल रंगों को फ़िल्टर करने के लिए WHERE क्लॉज शामिल करने के लिए अनुकूलित किया, जहां कोई भी घटक अधिकतम 20 के लिए भिन्न होता है।
अपडेट करें: एक और नज़र के बाद, 20 की सीमा जोड़ने से परिणाम बहुत खराब हो सकते हैं, क्योंकि मुझे अंतरिक्ष में कम से कम एक बिंदु मिला है, जिसके लिए यह सही है।:
SELECT
c.rgb_r, c.rgb_g, c.rgb_b,
DELTA_E_CIE2000(
25.805780252087963, 53.33446637366859, -45.03961353720049,
c.lab_l, c.lab_a, c.lab_b,
1.0, 1.0, 1.0) AS de2000
FROM color c
WHERE
c.lab_l BETWEEN 25.805780252087963 - 20 AND 25.805780252087963 + 20
AND c.lab_a BETWEEN 53.33446637366859 - 20 AND 53.33446637366859 + 20
AND c.lab_b BETWEEN -45.03961353720049 - 20 AND -45.03961353720049 + 20
ORDER BY de2000 ;
मैंने आपकी स्क्रिप्ट के साथ तालिका को 100000 यादृच्छिक रंगों से भर दिया और परीक्षण किया:
अनुक्रमित के बिना समय:44006,851 एमएस
अनुक्रमित और श्रेणी क्वेरी के साथ समय:1293,092 एमएस
आप इस WHERE क्लॉज को delta_e_cie1976_query
. में जोड़ सकते हैं मेरे यादृच्छिक डेटा पर भी, यह क्वेरी समय को ~110 ms से ~22 ms तक कम कर देता है।
BTW:मुझे आनुभविक रूप से 20 नंबर मिला:मैंने 10 के साथ प्रयास किया, लेकिन केवल 380 रिकॉर्ड प्राप्त किए, जो थोड़ा कम लगता है और कुछ बेहतर विकल्पों को बाहर कर सकता है क्योंकि सीमा 100 है। 20 के साथ पूरा सेट 2900 पंक्तियों का था और एक निष्पक्ष हो सकता है सुनिश्चित करें कि निकटतम मैच होंगे। मैंने DELTA_E_CIE2000 या L*a*b* कलर स्पेस का विस्तार से अध्ययन नहीं किया है, इसलिए थ्रेशोल्ड को वास्तव में सही होने के लिए विभिन्न घटकों के साथ समायोजन की आवश्यकता हो सकती है, लेकिन गैर-दिलचस्प डेटा को बाहर करने का सिद्धांत धारण करता है।
Delta E CIE 2000 को C में फिर से लिखें
जैसा कि आप पहले ही कह चुके हैं, डेल्टा ई सीआईई 2000 जटिल है और एसक्यूएल में लागू करने के लिए काफी अनुपयुक्त है। यह वर्तमान में मेरे लैपटॉप पर लगभग 0.4 एमएस प्रति कॉल का उपयोग करता है। इसे सी में कार्यान्वित करने से इसे काफी तेज करना चाहिए। PostgreSQL SQL फ़ंक्शन के लिए डिफ़ॉल्ट लागत को 100 और C फ़ंक्शन को 1 के रूप में असाइन करता है। मुझे लगता है कि यह वास्तविक अनुभव पर आधारित है।
अपडेट करें: चूंकि यह मेरी एक खुजली को भी खरोंचता है, मैंने डेल्टा ई फ़ंक्शंस को C में colormath मॉड्यूल से PostgreSQL एक्सटेंशन के रूप में फिर से लागू किया, जो PGXN . इसके साथ मैं 100k रिकॉर्ड के साथ तालिका से सभी रिकॉर्ड्स को क्वेरी करते समय CIE2000 के लिए लगभग 150x का स्पीडअप देख सकता हूं।
इस सी फ़ंक्शन के साथ, मुझे 100k रंगों के लिए 147 एमएस और 160 एमएस के बीच क्वेरी समय मिलता है। अतिरिक्त WHERE के साथ, क्वेरी का समय लगभग 20 ms है, जो मुझे काफी स्वीकार्य लगता है।
सर्वश्रेष्ठ, लेकिन उन्नत समाधान
हालाँकि, चूंकि आपकी समस्या 3-आयामी अंतरिक्ष में निकटतम पड़ोसी खोज है, आप K-निकटतम-पड़ोसी अनुक्रमण का उपयोग कर सकते हैं जो PostgreSQL संस्करण 9.1 से ।
उसके काम करने के लिए, आप L*a*b* घटकों को घन . यह एक्सटेंशन अभी तक डिस्टेंस ऑपरेटर का समर्थन नहीं करता है ( यह काम कर रहा है ), लेकिन फिर भी, यह डेल्टा ई दूरियों का समर्थन नहीं करेगा और आपको इसे सी एक्सटेंशन के रूप में फिर से लागू करने की आवश्यकता होगी।
इसका मतलब है कि GiST इंडेक्स ऑपरेटर क्लास (btree_gist PostgreSQL एक्सटेंशन
को लागू करना contrib यह करता है) डेल्टा ई दूरियों के अनुसार अनुक्रमण का समर्थन करने के लिए। अच्छा हिस्सा यह है कि आप डेल्टा ई के विभिन्न संस्करणों के लिए विभिन्न ऑपरेटरों का उपयोग कर सकते हैं, उदाहरण के लिए। <->
डेल्टा ई सीआईई 2000 और <#>
. के लिए डेल्टा ई सीआईई 1976 के लिए और प्रश्न वास्तव में बहुत तेज़
होंगे डेल्टा ई सीआईई 2000 के साथ भी छोटी सीमा के लिए।
अंत में यह इस बात पर निर्भर हो सकता है कि आपकी (व्यावसायिक) आवश्यकताएं और बाधाएं क्या हैं।