2013-04-03 55 views
8

讓我們假設我們有一張人名錶(姓名,地址,SSN等)。SQL和模糊比較

我們希望找到與指定人員「非常相似」的所有行。 我想實現A和表People中所有行的某種模糊邏輯比較。將有幾個模糊推理規則分別在幾列上工作(例如,3個模糊規則爲姓名,2個規則在姓氏上,5個規則在地址上)

問題是以下兩種方法哪種更好,爲什麼?

  1. 實現所有模糊規則的存儲過程和使用一個沉重的SELECT語句返回「非常相似」 A.所有行這種做法可能包括使用同音,SIM指標等

  2. 實施一個或多個簡單的SELECT語句,它返回的結果較不準確,「與A非常相似」,然後將所有返回的行(數據庫外部)與模糊比較A得到「非常相似」的行。所以模糊比較將以我喜歡的編程語言實現。

表的人應該有多達50萬行,我想每天賺取大約500-1000查詢這個樣子。我使用MySQL(但這還有待考慮)。

+0

請說出您正在使用的rdbms。 – 2013-04-03 23:19:29

+0

爲什麼不在你的select中使用一個case,如果它是相似的則返回1,否則返回0,然後求和所有的列。那些超過特定範圍的人應該被退回。看起來像是解決您的問題的簡單方法。 – 2013-04-03 23:30:18

+1

@JesusZamora:問題是,首先相似性的價值可能是浮動的(例如0.43),這就是爲什麼我在談論「模糊比較」。第二個問題是,計算這種相似性的價值相當複雜,我不知道哪種方法會更優化。 – 2013-04-03 23:38:07

回答

3

我真的不認爲這是一個明確的答案,因爲它取決於在這個問題無法得到的信息。無論如何,太長的評論。

DBMS擅長根據索引檢索信息。數據庫服務器在繁重的計算中浪費時間是沒有意義的,除非它專用於此特定目的(如@Adrian所回答的那樣)。

因此,您的客戶端應用程序應該委託給DBMS的在規則規定的信息檢索。

如果計算是次要的,都可以在服務器上完成。否則,把它拉進客戶端系統。

第二種方法的缺點在於數據從服務器到客戶端和連接建立的數行的量。所以,通常它是服務器中計算和數據傳輸之間的折中。要根據模糊規則的特性來達到平衡。

編輯:我在評論中看到,你幾乎肯定必須在客戶端實現代碼。在這種情況下,爲了維護的目的,你應該考慮一個額外的標準,代碼位置,即試圖讓所有相關的代碼在系統(和語言)之間傳播。

1

既然你還在考慮什麼DB使用PostgreSQL有fuzzystrmatch模塊,提供萊文斯坦和探測功能。另外,您可能需要按照here的描述查看pg_trm模塊。也許你也可以使用soundex()將這個索引放在列上,這樣你就不必每次計算了。 但是你似乎過早地進行了優化,所以我的建議是使用pg進行測試,然後想知道是否需要優化,所提供的數字似乎並不是很多,你幾乎有兩分鐘的時間來運行一個查詢。

+0

如果我決定使用第一種方法,使用[fuzzystrmatch](http://www.postgresql.org/docs/current/static/fuzzystrmatch.html)中的levenshtein和soundex函數聽起來相當不錯。但是我幾乎可以肯定,我將不得不使用我自己的程序來處理至少一些指標(模糊規則),所以使用這些模塊並不能解決所有問題。無論如何,我仍然不確定在DB內部做什麼更好,爲什麼。 – 2013-04-04 00:16:27

+0

更準確地說,關於要求。每天將會有500-1000個查詢,但它應該儘可能快地完成(比如不到一小時) – 2013-04-04 00:20:20

+0

@ running.t運行levenshtein()函數在我的筆記本電腦上連續運行的時間少於半秒,diffrence()是相似的,所以你不應該擔心至少在db中這樣做。 – 2013-04-04 01:27:46

2

我會說你最好使用簡單的選擇,讓你可以在最近的比賽沒有錘擊數據庫,然後做繁重的工作在應用層。我建議這個解決方案的原因是可擴展性:如果你在應用程序層中做了繁重的工作,那麼你的問題就是一個完美的用例 - 一個map-reduce樣式的解決方案,你可以在節點之間分配相似處理並獲得結果返回比通過數據庫更快;另外,這樣,您不會鎖定數據庫並放慢可能同時進行的其他任何操作。

+0

我認爲這是我要實現這一點的方式。但我仍然想知道這種方法是否存在任何缺點或潛在風險。 – 2013-04-09 09:54:17

+1

缺點將基於您的情況:如果您的數據庫服務器通常具有比應用程序服務器更多的未使用容量,則需要將更多工作分攤到數據庫服務器。如果他們在同一個盒子裏,你必須通過兩種方式進行基準測試,才能針對特定情況獲得最佳答案。 – Adrian 2013-04-10 22:17:09

0

我會考慮的一個選項是在「人物塔爾」中添加一個人物的SoundEx值。

我做連接使用

Select [Column} 
From People P 
    Inner join TableA A on Soundex(A.ComarisonColumn) = P.SoundexColumn 

這會在具有從人民表的SoundEx列相同的SoundEx值表A返回任何東西。

我還沒有使用這種查詢大小的表,但我沒有看到與嘗試它的問題。您還可以將該SoundExColumn編入索引以提高性能。