Postgresql

如何在PostgreSQL中儲存和查詢匹配前綴或後綴的字元串?

  • June 30, 2022

假設我有 100 種不同語言的 100 萬個單詞(所以 1 億個單詞,每個單詞的字母範圍從 10 個字元到 200 個字元不等,儘管僅中文就有 80k 個“字元”!我也想在中文上支持它)。由於各種其他原因,這些詞儲存在數據庫中,因此如果可能,我們最好從數據庫中使用它們。

您將向words表中添加什麼(假設該words.text屬性具有來自 100 種不同語言中的任何一種的字元串)以允許前綴/後綴匹配查詢?如果絕對必要的話,也許我們有不同語言的不同表格。

要在 PostgreSQL 中進行前綴查詢(我認為沒有索引?),您可以執行以下操作:

select * from words where text like 'cal%'

用於搜尋以 . 開頭的所有單詞cal。但對於這種規模的數據集,這是最有效/可擴展的方法嗎?在我的職業生涯中,我對這些類型的查詢沒有太多經驗。如果不是,推薦的、標準的、理想的或其他有效的方法是什麼(就數據大小和查詢性能而言)?您需要添加哪些類型的索引來提高效率?如果 PostgreSQL 不能有效地做到這一點(或者 SQL),那麼在高層次上,首選的解決方案是什麼?我知道記憶體中的嘗試是一個很好的解決方案,但這是否比 PostgreSQL 解決方案好得多(如果可能的話)?

我已經在考慮,基於這個答案,使用 26 個英語索引,以便能夠找到所有能夠解讀某些輸入的單詞(所以CAUDKfindsduck等等),但不確定是否可以將類似的解決方案擴展到前綴/後綴搜尋。另外,對於處理較大的字母表和其他類型的查詢,這似乎也不是那麼有效(就數據大小而言)。

實際上,大多數語言的單詞少於 200k,而且一開始可能會少於 20k。我說的不僅僅是英語,還有藏文ལྷ་སའི་སྐད་、中文、韓文、梵文和梵文等。

如果在這多種不同的語言中實現這是一項極其複雜的任務,請僅對如何解決它的基本願景進行佈局,並指出要進行更多研究的關鍵位置。如果可以超深入地在單個語言的基礎上實現複雜的解決方案(例如,中文在解決方案方面與英語的方式可能不同),我真的不想為每個語言實現複雜和獨特的東西語。理想情況下,它只是“基於字元”的東西,可以應用跨語言。因為在我對全文搜尋實現的簡要研究中,這似乎不是我需要的,但不確定。

在大多數情況下,前綴搜尋與字元串搜尋一樣有效,但會更早停止。

對於後綴搜尋,您必須儲存您的單詞反轉(desrever),然後搜尋反轉後綴(de% 而不是 %ed)。

對於 anagram/scramble 搜尋,您必須按字母順序儲存單詞(anagram -> aaagmnr)

跟進我對另一個問題的回答:

對於前綴搜尋,我建議使用 in-memory trie。這本質上是一棵樹,每個唯一單詞對應於樹下唯一的從根到葉的路徑,每個樹節點有 1 個字母。作為一種潛在的記憶體優化,您可以使用基數樹,它是一個包含與其父節點合併的單子節點的樹。這是從上一個連結中獲取的基數樹中前綴搜尋如何工作的圖表:

在此處輸入圖像描述

這棵樹可以使用多個字母來容納來自多種語言的單詞。這棵樹的最大分支因子將對應於所有字母表中的字元數。

在實現方面,我的建議是查詢處理過程從數據庫中載入整個單詞列表並在初始化時構造 trie。它的建構速度應該相對較快。

可以通過使用包含反轉單詞的第二個 trie 來執行後綴搜尋。

至於“解擾”操作,我確實相信我在另一個問題中的每字元索引解決方案最適合具有小字母的語言。但是對於具有大字母的語言,這將是非常低效的,因為它需要 O(MN) 空間,其中 M 是單詞的數量,N 是字母字元的數量。對於此類語言,由於每個單詞通常只有少量字元(中文每個單詞大約有 1.6 個字元 -來源),更有效的方法是簡單地構造一個記憶體中的雜湊映射,將每個字元映射到包含該字元的所有單詞(或單詞索引)的列表。然後可以通過在此雜湊圖中查找查詢的每個字元並獲取返回列表的交集來處理給定的解擾查詢。最後的過濾步驟可用於處理多重性;或者,雜湊映射值本身可以是將多重性映射到單詞的映射。

多數據庫索引方法在其底層有效地執行了類似於這種更通用方法的操作,但由於採用了通用數據庫機制,因此應該更加優化。您可以考慮只嘗試單一語言獨立實現的通用方法。

引用自:https://dba.stackexchange.com/questions/313922