pg_trgm
模組提供函式和運算子,用於基於三字母組匹配來確定字母數字文字的相似度,以及支援快速查詢相似字串的索引運算子類。
此模組被認為是“受信任的”,這意味著非超級使用者也可以在其擁有的資料庫上安裝它,前提是他們具有 CREATE
許可權。
三字母組是從字串中取出的三個連續字元組成的組。我們可以透過計算兩個字串共享的三字母組的數量來衡量它們的相似度。這個簡單的想法被證明在衡量許多自然語言單詞的相似度方面非常有效。
pg_trgm
在從字串提取三字母組時會忽略非單詞字元(非字母數字字元)。在確定字串所包含的三字母組集合時,每個單詞被認為前面有兩個空格,後面有一個空格。例如,字串 “cat
” 的三字母組集合是 “ c
”、“ ca
”、“cat
” 和 “at
”。字串 “foo|bar
” 的三字母組集合是 “ f
”、“ fo
”、“foo
”、“oo
”、“ b
”、“ ba
”、“bar
” 和 “ar
”。
由 pg_trgm
模組提供的函式在 表 F.26 中列出,運算子在 表 F.27 中列出。
表 F.26. pg_trgm
函式
請考慮以下示例
# SELECT word_similarity('word', 'two words'); word_similarity ----------------- 0.8 (1 row)
在第一個字串中,三字母組集合是 {" w"," wo","wor","ord","rd "}
。在第二個字串中,有序三字母組集合是 {" t"," tw","two","wo "," w"," wo","wor","ord","rds","ds "}
。第二個字串中最相似的有序三字母組集合是 {" w"," wo","wor","ord"}
,相似度為 0.8
。
此函式返回的值可以大致理解為第一個字串與第二個字串的任何子串之間的最大相似度。但是,此函式不會為匹配範圍的邊界新增填充。因此,第二個字串中存在的額外字元數量不會被考慮,除了不匹配的詞語邊界。
同時,strict_word_similarity
會選擇第二個字串中的一個詞語範圍。在上面的示例中,strict_word_similarity
會選擇單個詞語 'words'
的範圍,其三字母組集合為 {" w"," wo","wor","ord","rds","ds "}
。
# SELECT strict_word_similarity('word', 'two words'), similarity('word', 'words'); strict_word_similarity | similarity ------------------------+------------ 0.571429 | 0.571429 (1 row)
因此,strict_word_similarity
函式對於查詢整個詞語的相似度很有用,而 word_similarity
則更適合查詢詞語部分的相似度。
表 F.27. pg_trgm
運算子
運算子 描述 |
---|
如果其引數的相似度大於由 |
如果第一個引數中的三字母組集合與第二個引數中的連續有序三字母組集合的相似度大於由 |
|
如果其第二個引數具有匹配詞語邊界的連續有序三字母組集合,並且其與第一個引數的三字母組集合的相似度大於由 |
|
返回引數之間的“距離”,即 1 減去 |
返回引數之間的“距離”,即 1 減去 |
|
返回引數之間的“距離”,即 1 減去 |
|
pg_trgm
模組提供 GiST 和 GIN 索引運算子類,允許您在文字列上建立索引,以實現非常快速的相似度搜索。這些索引型別支援上述相似度運算子,並且還支援基於三字母組的 LIKE
、ILIKE
、~
、~*
和 =
查詢的索引搜尋。在 pg_trgm
的預設構建中,相似度比較是不區分大小寫的。不支援不等價運算子。請注意,對於相等運算子,這些索引可能不如常規 B-tree 索引高效。
示例:
CREATE TABLE test_trgm (t text); CREATE INDEX trgm_idx ON test_trgm USING GIST (t gist_trgm_ops);
或
CREATE INDEX trgm_idx ON test_trgm USING GIN (t gin_trgm_ops);
gist_trgm_ops
GiST opclass 使用點陣圖簽名來近似三字母組集合。其可選的整數引數 siglen
決定了簽名的長度(以位元組為單位)。預設長度為 12 位元組。有效的簽名長度值為 1 到 2024 位元組之間。更長的簽名會導致更精確的搜尋(掃描索引的一部分和更少的堆頁面),但會增加索引的大小。
使用 32 位元組簽名長度建立此類索引的示例
CREATE INDEX trgm_idx ON test_trgm USING GIST (t gist_trgm_ops(siglen=32));
此時,您將在 t
列上有一個索引,可用於相似度搜索。典型的查詢是
SELECT t, similarity(t, 'word
') AS sml FROM test_trgm WHERE t % 'word
' ORDER BY sml DESC, t;
這將返回文字列中與 word
足夠相似的所有值,並按最佳匹配到最差的順序排序。即使在非常大的資料集上,索引也將被用來使此操作快速執行。
上面查詢的一個變體是
SELECT t, t <-> 'word
' AS dist
FROM test_trgm
ORDER BY dist LIMIT 10;
GiST 索引可以非常有效地實現這一點,但 GIN 索引不能。當只需要最接近的匹配項時,它通常會比第一種方法效果更好。
您還可以使用 t
列上的索引來進行詞語相似度或嚴格詞語相似度搜索。典型的查詢是
SELECT t, word_similarity('word
', t) AS sml FROM test_trgm WHERE 'word
' <% t ORDER BY sml DESC, t;
和
SELECT t, strict_word_similarity('word
', t) AS sml FROM test_trgm WHERE 'word
' <<% t ORDER BY sml DESC, t;
這將返回文字列中所有其對應的有序三字母組集合的連續部分與 word
的三字母組集合足夠相似的值,並按最佳匹配到最差的順序排序。即使在非常大的資料集上,索引也將被用來使此操作快速執行。
上面查詢的可能變體是
SELECT t, 'word
' <<-> t AS dist
FROM test_trgm
ORDER BY dist LIMIT 10;
和
SELECT t, 'word
' <<<-> t AS dist
FROM test_trgm
ORDER BY dist LIMIT 10;
GiST 索引可以非常有效地實現這一點,但 GIN 索引不能。
從 PostgreSQL 9.1 開始,這些索引型別還支援 LIKE
和 ILIKE
的索引搜尋,例如
SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';
索引搜尋透過從搜尋字串中提取三字母組,然後在索引中查詢它們來實現。搜尋字串中的三字母組越多,索引搜尋就越有效。與 B-tree 搜尋不同,搜尋字串不必是左錨定的。
從 PostgreSQL 9.3 開始,這些索引型別還支援正則表示式匹配(~
和 ~*
運算子)的索引搜尋,例如
SELECT * FROM test_trgm WHERE t ~ '(foo|bar)';
索引搜尋透過從正則表示式中提取三字母組,然後在索引中查詢它們來實現。從正則表示式中提取的三字母組越多,索引搜尋就越有效。與 B-tree 搜尋不同,搜尋字串不必是左錨定的。
對於 LIKE
和正則表示式搜尋,請記住,沒有可提取三字母組的模式將退化為完全索引掃描。
GiST 和 GIN 索引之間的選擇取決於 GiST 和 GIN 的相對效能特徵,這些在別處有討論。
三字母組匹配是與全文索引結合使用的非常有用的工具。特別是它可以幫助識別全文檢索機制無法直接匹配的拼寫錯誤的輸入單詞。
第一步是生成一個包含文件中所有唯一單詞的輔助表
CREATE TABLE words AS SELECT word FROM ts_stat('SELECT to_tsvector(''simple'', bodytext) FROM documents');
其中 documents
是一個具有文字欄位 bodytext
的表,我們希望對其進行搜尋。使用 simple
配置和 to_tsvector
函式而不是使用特定語言的配置的原因是,我們想要原始(未詞幹化)單詞的列表。
接下來,在單詞列上建立三字母組索引
CREATE INDEX words_idx ON words USING GIN (word gin_trgm_ops);
現在,可以使用類似於前面示例的 SELECT
查詢來為使用者搜尋詞中的拼寫錯誤單詞提供拼寫建議。一個有用的額外測試是要求選定的單詞與拼寫錯誤單詞的長度也相似。
由於 words
表是作為一個獨立的、靜態表生成的,它需要定期重新生成,以便與文件集合保持相對同步。保持完全同步通常是不必要的。
GiST 開發站點 http://www.sai.msu.su/~megera/postgres/gist/
Tsearch2 開發站點 http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/
Oleg Bartunov <oleg@sai.msu.su>
,莫斯科,莫斯科大學,俄羅斯
Teodor Sigaev <teodor@sigaev.ru>
,莫斯科,Delta-Soft Ltd.,俄羅斯
Alexander Korotkov <a.korotkov@postgrespro.ru>
,莫斯科,Postgres Professional,俄羅斯
文件:Christopher Kings-Lynne
本模組由 Delta-Soft Ltd.(俄羅斯莫斯科)贊助。
如果您在文件中發現任何不正確、與您在該特定功能上的經驗不符或需要進一步澄清的內容,請使用 此表單 報告文件問題。