किसी अभिव्यक्ति पर कुल LIKE क्वेरी को गति देने के लिए एक इंडेक्स कैसे बनाएं?


20

मैं शीर्षक में गलत सवाल पूछ सकता हूं। यहाँ तथ्य हैं:

मेरे ग्राहक सेवा लोक को हमारे Django- आधारित साइट के प्रशासन इंटरफ़ेस पर ग्राहक के लुकअप करते समय धीमी प्रतिक्रिया समय के बारे में शिकायत है।

हम Postgres का उपयोग कर रहे हैं 8.4.6। मैंने धीमी क्वेरी लॉग करना शुरू किया, और इस अपराधी की खोज की:

SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')

इस क्वेरी को चलाने में 32 सेकंड से अधिक समय लग रहा है। यहाँ क्वेरी योजना EXPLAIN द्वारा प्रदान की गई है:

QUERY PLAN
Aggregate  (cost=205171.71..205171.72 rows=1 width=0)
  ->  Seq Scan on auth_user  (cost=0.00..205166.46 rows=2096 width=0)
        Filter: (upper((email)::text) ~~ '%DEYK%'::text)

क्योंकि यह Django ORM द्वारा Django QuerySet द्वारा बनाई गई एक क्वेरी है जो Django एडमिन एप्लिकेशन द्वारा जेनरेट की गई है, मेरे पास खुद इस क्वेरी पर कोई नियंत्रण नहीं है। एक सूचकांक तार्किक समाधान की तरह लगता है। मैंने इसे गति देने के लिए एक इंडेक्स बनाने की कोशिश की, लेकिन इससे कोई फर्क नहीं पड़ा:

CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))

मैं क्या गलत कर रहा हूं? मैं इस क्वेरी को कैसे गति दे सकता हूं?

जवाबों:


21

PostgreSQL 8.4 में LIKE/ के लिए कोई अनुक्रमणिका समर्थन नहीं है - बाएं लंगर वाले खोज शब्दों को छोड़कर ।ILIKE

चूंकि PostgreSQL 9.1 अतिरिक्त मॉड्यूल pg_trgmGIN और GiST ट्रिग्राम सूचकांकों के लिए ऑपरेटर कक्षाएं प्रदान करता है जो LIKE/ ILIKEया नियमित अभिव्यक्ति (ऑपरेटरों ~और दोस्तों) का समर्थन करता है। प्रति डेटाबेस एक बार स्थापित करें:

CREATE EXTENSION pg_trgm;

उदाहरण GIN सूचकांक:

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

सम्बंधित:


2
यह वास्तव में सही उत्तर है।
vonPetrushev

9

आपके मैच की शुरुआत में '%' की वजह से वह इंडेक्स मदद करने वाला नहीं है - एक BTREE इंडेक्स केवल उपसर्गों और वाइल्डकार्ड से आपकी क्वेरी के प्रारंभ में मेल कर सकता है, जिसका अर्थ है कि देखने के लिए कोई निश्चित उपसर्ग नहीं है।

यही कारण है कि यह एक टेबल स्कैन कर रहा है और क्वेरी स्ट्रिंग के विरुद्ध प्रत्येक रिकॉर्ड का मिलान कर रहा है।

संभवतः आपको LIKE के साथ प्रतिस्थापन खोज करने के बजाय एक पूर्ण पाठ अनुक्रमणिका और पाठ मिलान संचालकों का उपयोग करने की आवश्यकता है जो आप इस समय हैं। आप प्रलेखन में पूर्ण पाठ खोज पर और अधिक जानकारी प्राप्त कर सकते हैं:

http://www.postgresql.org/docs/8.4/static/textsearch-intro.html

वास्तव में मैं उस पृष्ठ से नोटिस करता हूं कि LIKE जाहिरा तौर पर अनुक्रमणिकाओं का उपयोग कभी नहीं करता है, जो मुझे अजीब लगता है क्योंकि यह एक गैर-वाइल्डकार्ड उपसर्गों को BTREE सूचकांक का उपयोग कर हल करने में सक्षम होना चाहिए। कुछ त्वरित परीक्षणों से पता चलता है कि प्रलेखन शायद सही है, लेकिन उस स्थिति में जब आप क्वेरी का समाधान करने के लिए LIKE का उपयोग कर रहे हैं, तो अनुक्रमण की कोई राशि मदद करने वाली नहीं है।


यही मैं डरता था। क्या एक और तरह का सूचकांक है जो मदद करेगा? जैसा कि मैंने कहा, मैं क्वेरी को प्रभावित करने की अपनी क्षमता में थोड़ा विवश हूँ।
डेविड आइक

इसके अलावा, अग्रणी %एक आवश्यक विशेषता है: ग्राहक सेवा प्रतिनिधि को ग्राहक खातों को खोजने के लिए इसकी आवश्यकता होती है, खासकर जब ईमेल पते में एक टाइपो हो।
डेविड आईके

खैर, LIKE और फुल-टेक्स्ट इंडेक्सिंग पर थोड़े से शोध के बाद, और मैं आपकी बात देखने लगा हूँ।
डेविड आइक

अभी के लिए, मैंने अग्रणी वाइल्डकार्ड को दबाने का एक तरीका ढूंढ लिया है। यह पता चला है कि आप LIKE के साथ एक इंडेक्स का उपयोग कर सकते हैं, यदि आप एक उपयुक्त ऑपरेटर क्लास के साथ इंडेक्स बनाते हैं । डॉक्स यहां हैं: postgresql.org/docs/8.4/static/indexes-opclass.html
डेविड आईके

इसके अलावा, ब्लोट के लिए अपने डीबी की जांच करें। यदि आपको उस तालिका में बहुत अधिक ब्लोट मिला है, तो इसे स्कैन करने में लंबा समय लगने वाला है। यदि आपको कुछ समय कम मिल गया है, तो इसे प्राथमिक कुंजी पर क्लस्टर करें और देखें कि क्या यह तेज हो जाता है। यदि आप ब्लोट की जांच करना चाहते हैं, तो आप विश्लेषण चला सकते हैं, फिर यहां क्वेरी चला सकते हैं: wiki.postgresql.org/wiki/Show_database_bloat । अधिक सटीक मानों के लिए, उस पृष्ठ के नीचे देखें।
स्कॉट मारलोए
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.