आपकी क्वेरी बहुत अधिक इष्टतम है। सिंटैक्स बहुत छोटा नहीं होगा, क्वेरी बहुत तेज़ नहीं होगी:
SELECT name
FROM spelers
WHERE name LIKE 'B%' OR name LIKE 'D%'
ORDER BY 1;
यदि आप वास्तव में वाक्य रचना को छोटा करना चाहते हैं , तो शाखाओं के साथ एक नियमित अभिव्यक्ति का उपयोग करें :
...
WHERE name ~ '^(B|D).*'
या चरित्र वर्ग के साथ थोड़ा तेज़ :
...
WHERE name ~ '^[BD].*'
सूचकांक के बिना एक त्वरित परीक्षण SIMILAR TOमेरे लिए किसी भी मामले में की तुलना में तेजी से परिणाम देता है।
जगह में एक उपयुक्त बी-ट्री इंडेक्स के साथ, LIKEपरिमाण के आदेशों द्वारा इस दौड़ को जीतता है।
मैनुअल में पैटर्न मिलान के बारे में मूल बातें पढ़ें ।
बेहतर प्रदर्शन के लिए सूचकांक
यदि आप प्रदर्शन से चिंतित हैं, तो बड़ी तालिकाओं के लिए एक सूचकांक बनाएं:
CREATE INDEX spelers_name_special_idx ON spelers (name text_pattern_ops);
परिमाण के आदेशों द्वारा इस प्रकार की क्वेरी को तेज बनाता है। स्थानीय-विशिष्ट सॉर्ट क्रम के लिए विशेष विचार लागू होते हैं। मैनुअल में ऑपरेटर कक्षाओं के बारे में अधिक पढ़ें । यदि आप मानक "C" लोकेल का उपयोग कर रहे हैं (ज्यादातर लोग नहीं करते हैं), एक सादा सूचकांक (डिफ़ॉल्ट ऑपरेटर वर्ग के साथ) करेगा।
इस तरह के एक सूचकांक केवल बाएं-लंगर वाले पैटर्न (स्ट्रिंग की शुरुआत से मिलान) के लिए अच्छा है।
SIMILAR TOया बुनियादी बाईं-एंकर अभिव्यक्तियों के साथ नियमित अभिव्यक्ति इस सूचकांक का उपयोग कर सकते हैं, भी। लेकिन शाखाओं या चरित्र वर्गों के साथ नहीं (कम से कम पोस्टग्रेएसक्यूएल 9.0 पर मेरे परीक्षणों में)।(B|D)[BD]
ट्रिग्राम मैच या टेक्स्ट खोज विशेष GIN या GiST इंडेक्स का उपयोग करते हैं।
पैटर्न मिलान ऑपरेटरों का अवलोकन
LIKE( ~~) सरल और तेज है लेकिन अपनी क्षमताओं में सीमित है।
ILIKE( ~~*) मामला असंवेदनशील रूप।
pg_trgm दोनों के लिए सूचकांक समर्थन बढ़ाता है।
~ (रेगुलर एक्सप्रेशन मैच) शक्तिशाली है, लेकिन अधिक जटिल है और बुनियादी अभिव्यक्तियों से अधिक कुछ के लिए धीमा हो सकता है।
SIMILAR TOबस व्यर्थ है । एक अजीबोगरीब LIKEऔर नियमित भाव। मैं इसका इस्तेमाल कभी नहीं करता। निचे देखो।
% "समानता" ऑपरेटर है, जो अतिरिक्त मॉड्यूल द्वारा प्रदान किया गया हैpg_trgm। निचे देखो।
@@पाठ खोज ऑपरेटर है। निचे देखो।
pg_trgm - ट्रिग्राम मिलान
PostgreSQL 9.1 के साथ शुरुआत करके आप GIN या GiST इंडेक्स का उपयोग करके किसी भी / पैटर्न (और साथ सरल रीजैक्स पैटर्न ) के pg_trgmलिए सूचकांक समर्थन प्रदान करने के लिए विस्तार की सुविधा दे सकते हैं । LIKEILIKE~
विवरण, उदाहरण और लिंक:
pg_trgmइन ऑपरेटरों को भी प्रदान करता है :
% - "समानता" ऑपरेटर
<%(कम्यूटेटर %>:) - पोस्टग्रेज 9.6 या बाद में "शब्द_सिमिलिटी" ऑपरेटर
<<%(कम्यूटेटर %>>:) - पोस्टग्रेज 11 या बाद में "सख्त_शब्द_सिमिलिटी" ऑपरेटर
पाठ्य खोज
एक विशेष प्रकार का पैटर्न है जो अलग-अलग बुनियादी ढांचे और सूचकांक प्रकारों के साथ मेल खाता है। यह शब्दकोशों और स्टेमिंग का उपयोग करता है और दस्तावेजों में शब्दों को खोजने के लिए एक महान उपकरण है, खासकर प्राकृतिक भाषाओं के लिए।
उपसर्ग मिलान भी समर्थित है:
साथ ही वाक्यांश खोज Postgres 9.6 के बाद से:
मैनुअल में परिचय और ऑपरेटरों और कार्यों के अवलोकन पर विचार करें ।
फजी स्ट्रिंग मिलान के लिए अतिरिक्त उपकरण
अतिरिक्त मॉड्यूल fuzzystrmatch कुछ और विकल्प प्रदान करता है, लेकिन आमतौर पर प्रदर्शन उपरोक्त सभी के लिए अवर है।
विशेष रूप से, levenshtein()फ़ंक्शन के विभिन्न कार्यान्वयन सहायक हो सकते हैं।
नियमित अभिव्यक्तियाँ ( ~) हमेशा से अधिक तेज़ क्यों होती हैं SIMILAR TO?
उत्तर सीधा है। SIMILAR TOअभिव्यक्तियों को आंतरिक रूप से नियमित अभिव्यक्ति में फिर से लिखा जाता है। इसलिए, प्रत्येक SIMILAR TOअभिव्यक्ति के लिए, कम से कम एक तेज नियमित अभिव्यक्ति है (जो अभिव्यक्ति को फिर से लिखने के ओवरहेड को बचाता है)। उपयोग करने में कोई प्रदर्शन लाभ SIMILAR TO नहीं है ।
और सरल अभिव्यक्तियाँ जो LIKE( ~~) के साथ की जा सकती हैं वे LIKEवैसे भी तेज़ हैं ।
SIMILAR TOयह केवल PostgreSQL में समर्थित है क्योंकि यह SQL मानक के शुरुआती ड्राफ्ट में समाप्त हो गया है। उन्होंने अभी भी इससे छुटकारा नहीं पाया है। लेकिन इसे हटाने की योजना है और इसके बजाय रेगेक्सपी मैच शामिल हैं - या तो मैंने सुना।
EXPLAIN ANALYZEयह पता चलता है। बस किसी भी तालिका के साथ अपने आप को आज़माएं!
EXPLAIN ANALYZE SELECT * FROM spelers WHERE name SIMILAR TO 'B%';
पता चलता है:
...
Seq Scan on spelers (cost= ...
Filter: (name ~ '^(?:B.*)$'::text)
SIMILAR TOएक नियमित अभिव्यक्ति ( ~) के साथ फिर से लिखा गया है ।
इस विशेष मामले के लिए अंतिम प्रदर्शन
लेकिन और EXPLAIN ANALYZEखुलासा करता है। जगह-जगह उपरोक्त उल्लिखित सूचकांक के साथ प्रयास करें:
EXPLAIN ANALYZE SELECT * FROM spelers WHERE name ~ '^B.*;
पता चलता है:
...
-> Bitmap Heap Scan on spelers (cost= ...
Filter: (name ~ '^B.*'::text)
-> Bitmap Index Scan on spelers_name_text_pattern_ops_idx (cost= ...
Index Cond: ((prod ~>=~ 'B'::text) AND (prod ~<~ 'C'::text))
आंतरिक रूप से, एक सूचकांक (जाता है कि स्थान-बारे में पता नहीं के साथ text_pattern_opsया का उपयोग करते हुए स्थान C:) सरल बाएं लंगर डाले भाव इन पाठ पैटर्न ऑपरेटरों के साथ दोबारा लिखे जाने पर ~>=~, ~<=~, ~>~, ~<~। यह मामला है ~, ~~या एक SIMILAR TOजैसे।
varcharसाथ varchar_pattern_opsया charसाथ प्रकार पर अनुक्रमित के लिए भी यही सच है bpchar_pattern_ops।
इसलिए, मूल प्रश्न पर लागू किया जाता है, यह सबसे तेज़ संभव तरीका है :
SELECT name
FROM spelers
WHERE name ~>=~ 'B' AND name ~<~ 'C'
OR name ~>=~ 'D' AND name ~<~ 'E'
ORDER BY 1;
बेशक, यदि आपको आसन्न आद्याक्षरों की खोज करनी चाहिए, तो आप इसे और सरल बना सकते हैं:
WHERE name ~>=~ 'B' AND name ~<~ 'D' -- strings starting with B or C
~या के सादे उपयोग पर लाभ ~~छोटा है। यदि प्रदर्शन आपकी सर्वोपरि आवश्यकता नहीं है, तो आपको मानक ऑपरेटरों के साथ रहना चाहिए - जो आपके पास पहले से ही सवाल है।
s.nameअनुक्रमित?