2013-04-03 21 views
8

Załóżmy, że mamy tabelę osób (imię, nazwisko, adres, numer SSN itp.).Porównanie SQL i rozmyte

Chcemy znaleźć wszystkie wiersze, które są "bardzo podobne" do określonej osoby A. Chciałbym zaimplementować pewnego rodzaju porównanie logiki rozmytej A i wszystkich wierszy z tabeli Ludzie. Będzie kilka reguł wnioskowania rozmytego działających osobno na kilku kolumnach (np. 3 reguły rozmytej nazwy, 2 reguły na nazwisko, 5 reguł dotyczących adresu).

Pytanie brzmi: Które z poniższych dwóch podejść byłoby lepsze i dlaczego?

  1. Wdrożenie wszystkich reguł rozmytych jak procedury przechowywane i używać jednej ciężkie SELECT, aby powrócić wszystkie wiersze, które są „bardzo podobne” do A. Takie podejście może obejmować korzystanie Soundex, sim metryczny itp

  2. Wdrożenie jedna lub więcej instrukcji SELECT, które zwracają mniej dokładne wyniki, "raczej podobne" do A, a następnie rozmyte-porównać A ze wszystkimi zwróconymi wierszami (poza bazą danych), aby uzyskać wiersze "bardzo podobne". Tak rozmyte porównanie zostanie wdrożone w moim ulubionym języku programowania.

Tabela Ludzie powinni mieć do 500 tysięcy wierszy, a ja chciałbym zrobić około 500-1000 takich zapytań dziennie. Używam MySQL (ale to jeszcze nie jest brane pod uwagę).

+0

Proszę powiedzieć, jakich używasz rdbms. –

+0

Dlaczego nie użyć przypadku w swoim wyborze, który zwraca 1, jeśli jest podobny, 0 jeśli nie, a następnie sumuje wszystkie kolumny. Te, które są większe niż określony zakres, powinny zostać zwrócone. Wygląda na proste rozwiązanie twojego problemu. –

+1

@JesusZamora: Problem polega na tym, że przede wszystkim wartość podobieństwa może być zmienna (np. 0.43), dlatego mówiłem o "rozmytym porównaniu". Drugi problem polega na tym, że zliczanie tej wartości podobieństwa jest dość trudne i nie wiem, które z tych podejść byłyby bardziej optymalne. –

Odpowiedz

3

Nie sądzę, że istnieje ostateczna odpowiedź, ponieważ zależy to od informacji niedostępnych w pytaniu. W każdym razie, za długo na komentarz.

Systemy DBMS są dobre w wyszukiwaniu informacji według indeksów. Nie ma sensu, aby serwer db tracił czas na ciężkie obliczenia, chyba że jest dedykowany do tego konkretnego celu (jak odpowiedział @Adrian).

W związku z tym aplikacja kliencka powinna przekazać DBMS informacje wymagane przez reguły.

Jeśli obliczenia są niewielkie, wszystko można wykonać na serwerze. Inaczej, ściągnij to do systemu klienta.

Wadą drugiego podejścia jest ilość danych przesyłanych z serwera do klienta i liczba połączeń do ustalenia. Zwykle jest to kompromis pomiędzy obliczaniem i transferem danych na serwerze.Saldo, które należy osiągnąć w zależności od specyfiki reguł rozmytych.

Edycja: Widziałem w komentarzu, że prawie na pewno trzeba zaimplementować kod w kliencie. W takim przypadku należy rozważyć dodatkowe kryterium lokalizacji kodu dla celów związanych z konserwacją, tj. Spróbować uzyskać cały powiązany kod, nie rozpowszechniając go między systemami (i językami).

1

Ponieważ wciąż zastanawiasz się, do jakiego DB używać PostgreSQL ma moduł fuzzystrmatch, który zapewnia funkcje Levenshtein i Soundex. Możesz również zajrzeć do modułu pg_trm zgodnie z opisem podanym pod numerem here. Może mógłbyś też umieścić indeks na kolumnie używając soundex(), więc nie będziesz musiał tego za każdym razem kalkulować. Ale wydajesz się zoptymalizować przedwcześnie, więc moja rada byłaby do testowania przy użyciu pg, a następnie zastanawiam się, czy potrzebujesz zoptymalizować, czy nie, podanych liczb naprawdę nie wydaje się dużo uważać za prawie dwie minuty, aby uruchomić jedno zapytanie.

+0

Używanie funkcji levenshtein i soundex z [fuzzystrmatch] (http://www.postgresql.org/docs/current/static/fuzzystrmatch.html) brzmi całkiem nieźle, jeśli zdecyduję się na pierwsze podejście. Jednak jestem prawie pewien, że będę musiał użyć własnych procedur dla przynajmniej niektórych wskaźników (reguł rozmytych), więc użycie tych modułów nie rozwiąże wszystkiego. W każdym razie nadal nie jestem pewien, czy robienie wszystkiego w DB jest lepsze i dlaczego. –

+0

A ściślej mówiąc odnośnie wymagań. Będzie 500-1000 zapytań dziennie, ale powinno być zakończone tak szybko jak to możliwe (jak mniej niż godzina) –

+0

@ running.t uruchamianie funkcji levenshtein() milion razy z rzędu zajmuje mniej niż pół sekundy na moim laptopie , diffrence() jest podobny, więc nie powinieneś się martwić, przynajmniej o zrobieniu tego w db. –

2

Powiedziałbym, że najlepiej będzie, jeśli użyjesz prostych wyborów, aby uzyskać najbliższe dopasowania bez uderzania w bazę danych, a następnie wykonaj ciężkie podnoszenie w warstwie aplikacji. Powodem, dla którego zaproponowałbym to rozwiązanie, jest skalowalność: jeśli wykonujesz ciężkie podnoszenie w warstwie aplikacji, twój problem jest doskonałym przykładem użycia rozwiązania zmniejszającego mapę, w którym możesz dystrybuować przetwarzanie podobieństw między węzłami i uzyskiwać wyniki z powrotem znacznie szybciej niż w przypadku przełożenia go przez bazę danych; w ten sposób nie blokujesz bazy danych i nie spowalniasz żadnych innych operacji, które mogą się dziać w tym samym czasie.

+0

Myślę, że to jest sposób, w jaki zamierzam to wdrożyć. Nadal zastanawiam się, czy istnieją jakiekolwiek wady lub potencjalne ryzyko takiego podejścia. –

+1

Wady będą zależeć od sytuacji: jeśli serwer bazy danych ma zazwyczaj więcej niewykorzystanej pojemności niż serwer aplikacji, należy odłożyć więcej pracy na serwer bazy danych. Jeśli są na tym samym pudełku, musisz porównać je w jeden i drugi sposób, aby uzyskać najlepszą odpowiedź na konkretną sytuację. – Adrian

0

Opcja, którą chciałbym rozważyć, to dodanie kolumny do "Osoby Talbe", która jest wartością SoundEx danej osoby.

Zrobiłem dołącza użyciu

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

To będzie powrót niczego w TableA, który ma taką samą wartość SOUNDEX od ludzi Tables SOUNDEX kolumnie.

Nie użyłem tego rodzaju zapytania w tabelach o tym rozmiarze, ale nie widzę problemów z wypróbowaniem go. Możesz także indeksować SoundExColumn, aby pomóc w wydajności.