Jak wiadomo Solr posiada różne możliwości jeżeli chodzi o cachowanie danych – filterCache dla filtrów, queryResultCache dla wyników zapytań oraz documentCache do cachowania zapytań do szybkiego ich pobierania. Skupimy się dzisiaj na tym ostatnim i co możemy zrobić, aby wykorzystać go bardziej optymalnie.
Problem
Kiedy documentCache włączony jest w konfiguracji, po pobraniu dokumentu z Lucene jest on umieszczany w pamięci i trzymany tam do chwili usunięcia z documentCache (czy to przez wielkość cache lub commit). Taka operacja może być dosyć kosztowna – szczególnie dla dużych dokumentów. Możemy wyobrazić sobie dokumenty, które reprezentują treść strony uzyskanej przez skanowanie tekstu z książki. Problem polega na tym, że każdy wpis w documentCache, jeżeli nie jest ponownie użyty kwalifikuje się jako śmieć. Im więcej śmieci tym więcej pracy musi wykonać garbage collector, a tym samym Solr traci cykle procesora na ten proces zamiast na obsługę zapytań i indeksowanie danych. Może się to oczywiście wiązać z gorszą wydajnością. Na szczęście, zaczynając od Solr 6.5 jesteśmy sobie w stanie z tym poradzić, przynajmniej dla dużych pól typu stored.
Oznaczenie pola jako large
Zaczynając od Solr 6.5 dostaliśmy możliwość dodania dodatkowego atrybutu do definicji pola. W przypadku, kiedy nasze pole tekstowe ustawione jest jako stored=”true” oraz multiValued=”false” możemy dodać do niego atrybut large przyjmujący wartości true lub false (domyślnie false). Tak zdefiniowane pole nie będzie automatycznie umieszczane w documentCache, a umieszczana będzie jedynie referencja do niego z możliwością późniejszego załadowania.
Sprawdźmy różnicę
Ze względu na to, że jest to wpis typu szybkie spojrzenie nie będziemy wgłębiać się w kod i szczegóły, a jedynie sprawdzimy dwie kolekcje z tymi samymi danymi i polami. Struktura kolekcji składać się będzie z następujących pól:
- id – identtyfikator dokumentu,
- name – nazwa dokumentu,
- body – treść dokumentu, która w założeniach może być bardzo duża.
Jedna z kolekcji będzie miała ustawiony atrybut large=”true” dla pola body. Dodatkowo zaindeksujemy kilka dokumentów w celu sprawdzenia zachowania się Solr w przypadku obu konfiguracji.
Jeżeli mielibyście ochotę przeprowadzić ten sam test, poniżej przedstawiamy komendy użyte do jego przeprowadzenia (wszystkie pliki pochodzą z naszego konta na Github (https://github.com/solrpl/). Test polegał będzie na stworzeniu kolekcji, zaindeksowaniu danych, zadaniu zapytania, zebraniu statystyk. Powtórzymy go dla każdej z kolekcji za każdym razem uruchamiają nową, pustą instancję Solr. Wykorzystane komendy wyglądają następująco:
$ mkdir /tmp/solr $ mkdir /tmp/solr/collection_with_large $ mkdir /tmp/solr/collection_without_large $ wget https://github.com/solrpl/blog/tree/master/posts/large_field/data.xml /tmp/solr/data.xml $ wget https://github.com/solrpl/blog/tree/master/posts/large_field/collection_with_large/managed-schema /tmp/solr/collection_with_large/managed-schema $ wget https://github.com/solrpl/blog/tree/master/posts/large_field/collection_with_large/solrconfig.xml /tmp/solr/collection_with_large/solrconfig.xml $ wget https://github.com/solrpl/blog/tree/master/posts/large_field/collection_without_large/managed-schema /tmp/solr/collection_without_large/managed-schema $ wget https://github.com/solrpl/blog/tree/master/posts/large_field/collection_without_large/solrconfig.xml /tmp/solr/collection_without_large/solrconfig.xml $ bin/solr zk upconfig -z localhost:9983 -n config_with_large -d /tmp/collection_with_large $ bin/solr create_collection -c collection_with_large -n config_with_large -shards 1 -replicationFactor 1 $ curl -XPOST 'localhost:8983/solr/collection_with_large/update?commit=true' -H 'Content-Type:application/xml' --data-binary @/tmp/solr/data.xml $ curl 'localhost:8983/solr/collection_with_large/select?q=*:*'
A teraz stwórzmy drugą kolekcję używają pobranych danych:
$ bin/solr zk upconfig -z localhost:9983 -n config_without_large -d /tmp/collection_without_large $ bin/solr create_collection -c collection_without_large -n config_without_large -shards 1 -replicationFactor 1 $ curl -XPOST 'localhost:8983/solr/collection_without_large/update?commit=true' -H 'Content-Type:application/xml' --data-binary @/tmp/solr/data.xml $ curl 'localhost:8983/solr/collection_without_large/select?q=*:*'
Sprawdźmy teraz, jak wygląda wykorzystanie documentCache oraz co można znaleźć w jego środku. Tak wygląda documentCache w przypadku kolekcji z polem body oznaczonym jako large=”true”:
A tak wygląda wykorzystanie documentCache z polem body bez oznaczenia jako large=”true”:
Jak łatwo zauważyć pole oznaczone jako large=”true” nie zostało dodane do documentCache bezpośrednio, a została dodana „leniwa” referencja, która może być wykorzystana w razie potrzeby. Pozwala to na zmniejszenie rozmiaru dokumentów umieszczonych w documentCache, a tym samym mniejsze obciążenie pamięci i mniej pracy dla garbage collectora, co powinno przełożyć się na trochę lepszą wydajność Solr.