9.1 डेटाबेस में एक पोस्टग्राउंड में, मेरे पास table1
~ 1.5M पंक्तियों वाली एक तालिका और एक कॉलम है label
(इस प्रश्न के लिए सरलीकृत नाम)।
एक कार्यात्मक ट्रिग्राम-इंडेक्स है lower(unaccent(label))
( unaccent()
इसे इंडेक्स में इसके उपयोग की अनुमति देने के लिए अपरिवर्तनीय बनाया गया है)।
निम्नलिखित क्वेरी काफी तेज़ है:
SELECT count(*) FROM table1
WHERE (lower(unaccent(label)) like lower(unaccent('%someword%')));
count
-------
1
(1 row)
Time: 394,295 ms
लेकिन निम्नलिखित क्वेरी धीमी है:
SELECT count(*) FROM table1
WHERE (lower(unaccent(label)) like lower(unaccent('%someword and some more%')));
count
-------
1
(1 row)
Time: 1405,749 ms
और अधिक शब्दों को जोड़ना और भी धीमा है, हालांकि खोज कठोर है।
मैंने पहले शब्द के लिए एक सबकुछ चलाने के लिए एक सरल चाल की कोशिश की और फिर पूरी खोज स्ट्रिंग के साथ एक क्वेरी, लेकिन (दुख की बात है) क्वेरी प्लानर ने मेरी यंत्रणा के माध्यम से देखा:
EXPLAIN ANALYZE
SELECT * FROM (
SELECT id, title, label from table1
WHERE lower(unaccent(label)) like lower(unaccent('%someword%'))
) t1
WHERE lower(unaccent(label)) like lower(unaccent('%someword and some more%'));
तालिका 1 पर बिटमैप हीप स्कैन (लागत = 16216.01..16220.04 पंक्तियाँ = 1 चौड़ाई = 212) (वास्तविक समय = 1824.017..1824.019 पंक्तियाँ = 1 छोर = 1) Recheck Cond: ((निचला (अस्वीकार्य ((लेबल) :: टेक्स्ट))) ~~ '% someord%' :: टेक्स्ट) और (निचला (अस्वीकार्य (लेबल) :: टेक्स्ट)) ~~ '% someord और कुछ और % ':: पाठ)) -> तालिका 1 पर बिटमैप इंडेक्स स्कैन_ लैबल_हेन_जिन_ट्रैगम (लागत = 0.00..16216.01 पंक्तियों = 1 चौड़ाई = 0) (वास्तविक समय = 1823.900..1823.900 पंक्तियों = 1 छोरों = 1) सूचकांक कंडोम: ((कम (अस्वीकार्य ((लेबल) :: पाठ))) ~~ '% someord%' :: पाठ) और (कम (अस्वीकार्य (लेबल) :: पाठ)) ~~ '% someord और कुछ और % ':: पाठ)) कुल रनटाइम: 1824.064 एमएस
मेरी अंतिम समस्या यह है कि खोज स्ट्रिंग एक वेब इंटरफेस से आता है जो काफी लंबे तार भेज सकता है और इस प्रकार काफी धीमा हो सकता है और एक डॉस वेक्टर का गठन भी कर सकता है।
तो मेरे सवाल हैं:
- क्वेरी को कैसे गति दें?
- क्या इसे उप-क्षेत्रों में तोड़ने का एक तरीका है ताकि यह तेज हो?
- हो सकता है कि Postgres का बाद का संस्करण बेहतर हो? (मैं 9.4 की कोशिश की और यह तेजी से नहीं लगता है: अभी भी एक ही प्रभाव। शायद बाद के संस्करण?)
- शायद एक अलग अनुक्रमण रणनीति की आवश्यकता है?
unaccent
अपरिवर्तनीय घोषित किया । मैंने इसे सवाल से जोड़ा।
unaccent
मॉड्यूल को अपडेट करते हैं तो हैक अधिलेखित हो जाता है। इसके कारणों में से एक है कि मैं इसके बजाय एक फ़ंक्शन आवरण का सुझाव देता हूं।
unaccent()
एक अतिरिक्त मॉड्यूल द्वारा भी प्रदान किया गया है और पोस्टग्रेज डिफ़ॉल्ट रूप से फ़ंक्शन पर अनुक्रमित का समर्थन नहीं करता है क्योंकि यह नहीं हैIMMUTABLE
। आपने कुछ बदला होगा और आपने अपने प्रश्न में जो किया है उसका उल्लेख करना चाहिए। मेरी स्थायी सलाह: stackoverflow.com/a/11007216/939860 । इसके अलावा, ट्रिग्राम इंडेक्स बॉक्स के बाहर केस-असंवेदनशील मिलान का समर्थन करता है। आप इसे सरल बना सकते हैं:WHERE f_unaccent(label) ILIKE f_unaccent('%someword%')
- एक मिलान सूचकांक के साथ। विवरण: stackoverflow.com/a/28636000/939860 ।