2013-04-03 13 views
8

人のテーブル(名前、姓、住所、SSNなど)があるとしましょう。SQLとファジーの比較

特定の人物Aと「非常によく似ている」すべての行を検索したいとします。 AとテーブルPeopleからのすべての行の何らかのファジー論理比較を実装したいと思います。いくつかの列に別々に働くファジー推論ルールがいくつかあります(たとえば、名前の3つのファジールール、姓のルール2つ、住所のルール5つ)

質問はどちらですか?

  1. このアプローチ

  2. 実装する、シムメトリックのsoundexを使用することを含むことができるストアドプロシージャのように、すべてのファジールールを実装し、Aに「非常に類似」であるすべての行を返すために、1つの重SELECT文を使用より正確な結果を返す単純なSELECT文を1つ以上、「Aと似ている」とし、Aをすべての返された行(データベース外)とファジィ比較して「非常によく似た」行を得る。だから私の好きなプログラミング言語ではあいまいな比較が実装されるでしょう。

テーブル人数は500kまでです。これは1日あたり500-1000件のクエリを作成したいと考えています。私はMySQLを使用します(しかしこれはまだ考慮されていません)。

+0

使用しているrdbmsを教えてください。 –

+0

あなたのselectでそれが似ている場合は1を返し、そうでない場合は0を返し、すべての列を合計するケースを使用しないでください。特定の範囲を超える人は返却する必要があります。あなたの問題に対する簡単な解決策のようです。 –

+1

@JesusZamora:問題は、まず類似点の値が浮動小数点(例えば0.43)になる可能性があるということです。そのため、私は「あいまい比較」について話していました。第2の問題は、この類似性の価値を数えることはむしろ面倒であり、このアプローチのどちらがより最適であるかはわかりません。 –

答えて

3

質問には利用できない情報に依存するため、決定的な回答はないと思います。とにかく、コメントが長すぎます。

DBMSは、インデックスに従って情報を取得するのに適しています。この特別な目的(@Adrianが答えたように)専用でない限り、大量の計算でDBサーバーに時間を浪費させるのは意味がありません。

したがって、クライアントアプリケーションは、ルールに必要な情報の取得をDBMSに委任する必要があります。

計算がマイナーな場合は、すべてサーバー上で実行できます。そうでなければ、それをクライアントシステムに引き出します。

第2のアプローチの欠点は、サーバーからクライアントへのデータ転送量と確立する接続数にあります。したがって、通常、サーバーでの計算とデータ転送の間の妥協です。ファジールールの特異性に応じてバランスをとること。

編集:コメントには、ほとんどの場合、クライアントにコードを実装する必要があることがわかりました。その場合は、メンテナンスのために追加の基準、コードの場所を考慮する必要があります。つまり、関連するすべてのコードをシステム(および言語)間に広げないようにしてください。

1

PostgreSQLを使用するDBには、LevenshteinとSoundexの機能を提供するfuzzystrmatchモジュールがあります。また、hereのように、pg_trmモジュールを調べることもできます。たぶんインデックスをsoundex()を使って列に置くこともできるので、毎回計算する必要はありません。 しかし、あなたは時期尚早に最適化するように見えるので、私の助言はpgを使ってテストし、最適化する必要があるかどうか疑問に思うかもしれませんが、あなたが提供した数は実際には1つのクエリを実行するのに2分

+0

[fuzzystrmatch](http://www.postgresql.org/docs/current/static/fuzzystrmatch.html)のlevenshtein関数とsoundex関数を使用すると、最初のアプローチを使用することにすればかなりうまく聞こえます。しかし、私はほとんどのメトリクス(ファジィルール)のために私自身の手順を使用しなければならないと確信しているので、これらのモジュールを使用してもすべてを解決することはできません。とにかく、DBの中のすべてをやっている方が良い理由は分かっていません。 –

+0

そしてより正確な要件については。 1日に500〜1000件のクエリが発生しますが、できるだけ早く終了する必要があります(時間未満など) –

+0

@ running.t levenshtein()関数を実行すると、ラップトップで半分以下の時間がかかります、diffrence()は似ていますので、dbでそれを行うことについて少なくとも心配するべきではありません。 –

2

私は、シンプルな選択を使って、データベースを叩くことなくできるだけ近いものを得ることが最善だと言います。私がこのソリューションを提案する理由は、スケーラビリティです。アプリケーション層で重労働を起こした場合、問題は、ノード間で類似性の処理を分散して結果を得ることができるマップ・リダクション・スタイルのソリューションの完全な使用例ですあなたがデータベースに入れた場合よりもはるかに高速です。さらに、この方法では、データベースをロックしたり、同時に実行されている可能性のある他の操作を遅らせたりすることはありません。

+0

私はこれを実装する方法だと思います。しかし、私はまだこのアプローチの欠点や潜在的なリスクがあるかどうか疑問に思っています。 –

+1

短所はあなたの状況に基づいています:通常、データベースサーバーの使用容量がアプリケーションサーバーよりも多い場合は、データベースサーバーへの負荷を軽減する必要があります。同じボックスにいる場合は、特定の状況に最適な答えを得るために両方をベンチマークする必要があります。 – Adrian

0

私が考えているオプションは、その人のSoundEx値である "People Talbe"に列を追加することです。私がやった

は人々表SOUNDEX列から同じSOUNDEX値を持つTableAの中には何も戻ります

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

を使用して結合します。

私はそのサイズのテーブルでこの種のクエリを使用していませんが、試しても問題はありません。パフォーマンスに役立つように、そのSoundExColumnのインデックスを作成することもできます。