जिस तरह से आपके पास है, तालिका के प्रत्येक तत्व और हर दूसरे तत्व के बीच समानता की गणना की जानी चाहिए (लगभग एक क्रॉस जॉइन)। यदि आपकी तालिका में 1000 पंक्तियाँ हैं, तो पहले ., यह पहले से ही 1,00,000 (!) समानता गणना है उन्हें हालत के खिलाफ जांचा जा सकता है और क्रमबद्ध किया जा सकता है। बहुत तराजू।
SET pg_trgm.similarity_threshold
. का उपयोग करें और %
इसके बजाय ऑपरेटर। दोनों pg_trgm
. द्वारा प्रदान किए गए हैं मापांक। इस तरह, एक ट्राइग्राम जीआईएसटी इंडेक्स का बहुत प्रभाव के लिए उपयोग किया जा सकता है।
कॉन्फ़िगरेशन पैरामीटर pg_trgm.similarity_threshold
कार्यों को बदल दिया set_limit()
और show_limit()
पोस्टग्रेज 9.6 में। पदावनत कार्य अभी भी काम करते हैं (पोस्टग्रेज 13 के अनुसार)। साथ ही, पोस्टग्रेज 9.1 के बाद से GIN और GiST इंडेक्स के प्रदर्शन में कई तरह से सुधार हुआ है।
इसके बजाय प्रयास करें:
SET pg_trgm.similarity_threshold = 0.8; -- Postgres 9.6 or later
SELECT similarity(n1.name, n2.name) AS sim, n1.name, n2.name
FROM names n1
JOIN names n2 ON n1.name <> n2.name
AND n1.name % n2.name
ORDER BY sim DESC;
परिमाण के क्रम से तेज़, लेकिन फिर भी धीमा।
pg_trgm.similarity_threshold
एक "अनुकूलित" विकल्प है, जिसे किसी अन्य विकल्प की तरह संभाला जा सकता है। देखें:
- एक पैरामीटर पूछें (postgresql.conf सेटिंग) जैसे "max_connections"
हो सकता है कि आप पहले पूर्व शर्त (जैसे पहले अक्षरों का मिलान) जोड़कर संभावित जोड़ियों की संख्या सीमित करना चाहें क्रॉस जॉइनिंग (और समर्थन करता है कि एक मिलान कार्यात्मक सूचकांक के साथ)। क्रॉस जॉइन . का प्रदर्शन O(N²) . के साथ बिगड़ता है ।
यह काम नहीं करता क्योंकि आप आउटपुट कॉलम को WHERE
. में नहीं देख सकते या HAVING
खंड:
WHERE ... sim > 0.8
यह SQL मानक के अनुसार है (जिसे कुछ अन्य RDBMS द्वारा शिथिल रूप से नियंत्रित किया जाता है)। दूसरी ओर:
ORDER BY sim DESC
काम करता है क्योंकि आउटपुट कॉलम कर सकते हैं GROUP BY
. में उपयोग किया जा सकता है और ORDER BY
. देखें:
- पोस्टग्रेएसक्यूएल का पुन:उपयोग गणना परिणाम चुनिंदा क्वेरी में होता है
टेस्ट केस
मैंने अपने दावों को सत्यापित करने के लिए अपने पुराने परीक्षण सर्वर पर एक त्वरित परीक्षण चलाया।
PostgreSQL 9.1.4. EXPLAIN ANALYZE
. के साथ लिया गया समय (सर्वश्रेष्ठ 5) ।
CREATE TEMP table t AS
SELECT some_col AS name FROM some_table LIMIT 1000; -- real life test strings
GIN इंडेक्स के साथ परीक्षण का पहला दौर:
CREATE INDEX t_gin ON t USING gin(name gin_trgm_ops); -- round1: with GIN index
जीआईएसटी सूचकांक के साथ परीक्षण का दूसरा दौर:
DROP INDEX t_gin;
CREATE INDEX t_gist ON t USING gist(name gist_trgm_ops);
नई क्वेरी:
SELECT set_limit(0.8);
SELECT similarity(n1.name, n2.name) AS sim, n1.name, n2.name
FROM t n1
JOIN t n2 ON n1.name <> n2.name
AND n1.name % n2.name
ORDER BY sim DESC;
GIN इंडेक्स इस्तेमाल किया गया, 64 हिट:कुल रनटाइम:484.022 ms
GIST इंडेक्स इस्तेमाल किया गया, 64 हिट:कुल रनटाइम:248.772 ms
पुरानी क्वेरी:
SELECT (similarity(n1.name, n2.name)) as sim, n1.name, n2.name
FROM t n1, t n2
WHERE n1.name != n2.name
AND similarity(n1.name, n2.name) > 0.8
ORDER BY sim DESC;
GIN अनुक्रमणिका नहीं प्रयुक्त, 64 हिट:कुल रनटाइम:6345.833 ms
GIST अनुक्रमणिका नहीं इस्तेमाल किया गया, 64 हिट:कुल रनटाइम:6335.975 एमएस
अन्यथा समान परिणाम। सलाह अच्छी है। और यह सिर्फ 1000 पंक्तियों . के लिए है !
GIN या GiST?
GIN अक्सर बेहतर पठन प्रदर्शन प्रदान करता है:
- जीआईएसटी और जीआईएन इंडेक्स के बीच अंतर
लेकिन इस विशेष मामले में नहीं!
<ब्लॉककोट>इसे जीआईएसटी इंडेक्स द्वारा काफी कुशलता से लागू किया जा सकता है, लेकिन जीआईएन इंडेक्स द्वारा नहीं।
- विषम डेटा प्रकारों के साथ 3 फ़ील्ड पर बहु-स्तंभ अनुक्रमणिका