PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

लेटरल जॉइन ट्रिग्राम इंडेक्स का उपयोग नहीं कर रहा है

क्यों?

क्वेरी प्रिंसिपल पर इंडेक्स का उपयोग नहीं कर सकती है। आपको तालिका locations . पर एक अनुक्रमणिका की आवश्यकता होगी , लेकिन आपके पास टेबल पर है addresses

आप सेटिंग करके मेरे दावे की पुष्टि कर सकते हैं:

SET enable_seqscan = off;

(केवल आपके सत्र में, और केवल डिबगिंग के लिए। इसे उत्पादन में कभी भी उपयोग न करें।) ऐसा नहीं है कि अनुक्रमिक स्कैन की तुलना में अनुक्रमणिका अधिक महंगी होगी, पोस्टग्रेज़ के लिए इसे आपकी क्वेरी के लिए उपयोग करने का कोई तरीका नहीं है बिल्कुल भी

इसके अलावा:[INNER] JOIN ... ON true यह कहने का एक अजीब तरीका है CROSS JOIN ...

ORDER को हटाने के बाद इंडेक्स का इस्तेमाल क्यों किया जाता है? और LIMIT ?

क्योंकि Postgres इस सरल फ़ॉर्म को फिर से लिख सकते हैं:

SELECT *
FROM   addresses a
JOIN   locations l ON a.address ILIKE '%' || l.postalcode || '%';

आपको ठीक वही क्वेरी योजना दिखाई देगी. (कम से कम मैं पोस्टग्रेज 9.5 पर अपने परीक्षणों में करता हूं।)

समाधान

आपको locations.postalcode . पर एक इंडेक्स चाहिए . और LIKE . का उपयोग करते समय या ILIKE आपको अनुक्रमित अभिव्यक्ति भी लाने की आवश्यकता होगी (postalcode ) बाएं ऑपरेटर की तरफ। ILIKE ऑपरेटर के साथ कार्यान्वित किया जाता है ~~* और इस ऑपरेटर के पास कोई COMMUTATOR नहीं है (एक तार्किक आवश्यकता), इसलिए ऑपरेंड को इधर-उधर करना संभव नहीं है। इन संबंधित उत्तरों में विस्तृत विवरण:

एक समाधान ट्रिग्राम समानता ऑपरेटर % या इसका उलटा, डिस्टेंस ऑपरेटर <-> एक निकटतम पड़ोसी . में इसके बजाय क्वेरी (प्रत्येक स्वयं के लिए कम्यूटेटर है, इसलिए ऑपरेंड स्वतंत्र रूप से स्थान बदल सकते हैं):

SELECT *
FROM   addresses a
JOIN   LATERAL (
   SELECT *
   FROM   locations
   ORDER  BY postalcode <-> a.address
   LIMIT  1
   ) l ON address ILIKE '%' || postalcode || '%';

सबसे समान postalcode खोजें प्रत्येक address . के लिए , और फिर जांचें कि क्या वह postalcode . है वास्तव में पूरी तरह से मेल खाता है।

इस तरह, एक लंबा postalcode स्वचालित रूप से पसंद किया जाएगा क्योंकि यह छोटे postalcode . की तुलना में अधिक समान (छोटी दूरी) है वह भी मेल खाता है।

थोड़ी अनिश्चितता बनी हुई है। संभावित पोस्टल कोड के आधार पर, स्ट्रिंग के अन्य भागों में ट्रिगर मिलान के कारण झूठी सकारात्मकता हो सकती है। अधिक कहने के लिए प्रश्न में पर्याप्त जानकारी नहीं है।

यहां , [INNER] JOIN CROSS JOIN . के बजाय समझ में आता है, क्योंकि हम एक वास्तविक शामिल होने की शर्त जोड़ते हैं।

मैनुअल:

तो:

CREATE INDEX locations_postalcode_trgm_gist_idx ON locations
USING gist (postalcode gist_trgm_ops);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL में दिनांक तुलना

  2. SQL एकाधिक पंक्तियों में एक

  3. PostgreSQL ट्रिगर के माध्यम से वर्तमान पायथन दुभाषिया का लॉग स्टैकट्रेस

  4. कैसे pg_sleep_for () PostgreSQL में काम करता है

  5. किसी दिए गए कुंजी के प्रत्येक उदाहरण के लिए नवीनतम पंक्ति प्राप्त करने के लिए SQL क्वेरी