Rozproszone obliczanie IDF

Korzystając z SolrCloud, kiedy nasza kolekcja rozproszona jest pomiędzy wiele instancji Solr dotyka nas problem związany z obliczaniem tzw. odwrotnej częstotliwości dokumentu, czyli zmiennej określającej w jak dużej liczbie dokumentów występuje dany term. Problem w tym, iż domyślnie każda instanacja Solr trzyma dane na temat tej częstotliwości tylko sobie i nie dzieli się z innymi 😉 A co za tym idzie, im bardziej rozproszona jest nasza kolekcja, tym mniejsza jest precyzja naszego wyszukiwania. Zobaczmy zatem co możemy na to poradzić.

IDF i Solr

Wraz z premierą Lucene i Solr 6.0 domyślny algortym odpowiadający za score TF/IDF został zastąpiony algorytmem BM25, który powinien spisywać się lepiej ze względu na ograniczenia związane z maksymalnym wpływem częstotliwości termu.

W algorytmie BM25 współczynnik IDF obliczany jest w następujący sposób:

log(1 + (docCount - docFreq + 0.5)/(docFreq + 0.5))

Oznacza to, iż wartość IDF jest dużo szybciej i mocniej ograniczana w przypadku często występujących termów porównując to algorytmu TF/IDF obecnego przez we wcześniejszych wersjach Lucene i Solr.

Problemem jest to, iż informacja ja, domyślnie nie jest rozproszona. Oznacza to, że każdy shard przechowuje te informacje powodując, iż im bardziej kolekcja jest rozproszona, tym mniejsza dokładność. W większości przypadków nie jest to problem, jednak są takie gdzie jest to jednak coś, czym zaczynamy się przejmować. Dodatkowo, zmiany w architekturze kolekcji powodują zmiany w wyliczanym współczynniku score, nawet przy tych samych dokumentach. Jest to czasem niedopuszczalne.

Rozproszone IDF

Wraz z Solr 5.0 wprowadzona została możliwość skonfigurowania Solr do korzystania z rozproszonego obliczania IDF. Wystarczy do pliku solrconfig.xml dodać definicję statsCache i to wszystko. Na przykład:

<statsCache class="org.apache.solr.search.stats.ExactStatsCache" />

Proste prawda? Spójrzmy zatem jakie mamy opcje jeżeli chodzi o implementację:

LocalStatsCache – domyślna implementacja, kiedy nie mamy zdefiniowanego elementu statsCache w pliku solrconfig.xml. W tym wypadku sytuacja jest bardzo prosta – brak rozproszonego obliczania współczynnika IDF.

ExactStatsCache – implementacja cacheująca statystyki dotyczące termów wymagająca dodatkowego kroku podczas przetwarzania zapytania, tak aby zapytanie było analizowane na każdym shardzie wchodzącym w skład kolekcji. Może skutkować spadkiem wydajności zapytań ze względu na dodatkowe operacje.

ExactSharedStatsCache – implementacja podobna do opisywanej powyżej z tą różnicą, iż statystki są współdzielone pomiędzy żądaniami. Może skutkować większą wydajnością, niż ExactStatsCache, ale cechować go będzie większe wykorzystanie pamięci.

LRUStatsCache – w odróżnieniu do ExactStatsCache implementacja przechowująca statystyki dotyczące termów w LRU cache. Bazując na informacjach w cache’u Solr jest w stanie określić, czy dodatkowe zapytania są potrzebne tym samym zmniejszając ich częstotliwość, a tym samym zwiększając wydajność zapytań. Termy przechowywane są w mapach – liczba map determinowana jest liczbą shardów z których składa się kolekcja – map będzie tyle, ile jest shardów, a każdy shard trzyma jedną mapę ze statystykami termów.

Czy to działa?

Na tak postawione pytanie możemy odpowiedzieć tylko – trzeba to po prostu sprawdzić. W tym celu stworzymy dwie kolekcje distrib_idf oraz non_distrib_idf oraz zaindeksujemy przykładowe dane (konfigurację i dane można znaleźć na naszym Githubie – https://github.com/solrpl/blog). Każda z kolekcji będzie miała dwa shardy, jedną replikę, a sam klaster SolrCloud będzie składał się z dwóch instancji Solr.

Po zaindeksowaniu kilku przykładowych dokumentów możemy sprawdzić różnicę w wyliczaniu score zadając następujące zapytanie do każdej z kolekcji:

.../select?q=title:solr&fl=*,score

W przypadku kolekcji, która została skonfigurowana bez statsCache wyniki wyglądają następująco:

{
   "responseHeader":{
     "zkConnected":true,
     "status":0,
     "QTime":7,
     "params":{
       "q":"title:solr",
       "fl":"*,score"}},
   "response":{"numFound":4,"start":0,"maxScore":0.082873434,"docs":[
       {
         "id":"2",
         "title":["Solr document two"],
         "version":1633875263859195904,
         "score":0.082873434},
       {
         "id":"3",
         "title":["Solr document three"],
         "version":1633875263924207616,
         "score":0.082873434},
       {
         "id":"1",
         "title":["Solr document one"],
         "version":1633875263562448896,
         "score":0.082873434},
       {
         "id":"4",
         "title":["Solr document four"],
         "version":1633875263679889408,
         "score":0.082873434}]
   }}

W przypadku kolekcji w której statsCache jest skonfigurowany wyniki wyglądają następująco:

{
   "responseHeader":{
     "zkConnected":true,
     "status":0,
     "QTime":12,
     "params":{
       "q":"title:solr",
       "fl":"*,score"}},
   "response":{"numFound":4,"start":0,"maxScore":0.04789114,"docs":[
       {
         "id":"2",
         "title":["Solr document two"],
         "version":1633875264251363328,
         "score":0.04789114},
       {
         "id":"3",
         "title":["Solr document three"],
         "version":1633875264254509056,
         "score":0.04789114},
       {
         "id":"1",
         "title":["Solr document one"],
         "version":1633875264186351616,
         "score":0.04789114},
       {
         "id":"4",
         "title":["Solr document four"],
         "version":1633875264189497344,
         "score":0.04789114}]
   }}

Jest to oczywiście bardzo prosty przykład, jednak jak widać w przypadku kolekcji w której nie mamy skonfigurowanego statsCache score dokumentów jest prawie dwa razy wyższy. Ma to sens biorąc pod uwagę, iż term solr występuje w polu title cztery razy, po dwa razy w każdym shardzie. Oznacza to, iż kolekcja bez skonfigurowanego rozproszonego wyliczania IDF nie widzi pełnych danych.

Podsumowanie

Brak rozproszonego obliczania współczynnika IDF może powodować problemy – wtedy, kiedy jakość wyników wyszukiwania jest dla nas szczególnie ważna. Na szczęście, od wersji 5 silnika wyszukiwania Solr jesteśmy w stanie w bardzo prosty sposób włączyć rozproszony cache statystyk termów, a tym samym całkowicie rozprawić się z problemem. Oczywiście należy pamiętać, iż włączenie mechanizmu statsCache niesie za sobą obniżenie wydajności zapytań ze względu na konieczność dodatkowych operacji. Powodzenia 🙂

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners. View more
Cookies settings
Accept
Privacy & Cookie policy
Privacy & Cookies policy
Cookie name Active
Save settings
Cookies settings