Jednym z zagadnień, z którym musi się zmierzyć wiele z systemów informatycznych od wyszukiwarek, przez systemy e-commerce,  do  systemów intranetowych jest wyszukiwanie pełnotekstowe (ang. full-text search). W najprostszych przypadkach stosowane są rozwiązania wbudowane w silniki baz danych, z których korzysta dany system. Są jednak sytuacje, dla których wydajność takich rozwiązań jest niewystarczająca. Wtedy do akcji wkraczają rozwiązania takie jak Solr.

Solr (czyt. solar) to serwer wyszukiwania pełnotekstowego bazujący na bibliotece Lucene. Rozwijany jest przez Apache Foundation i rozpowszechniany na licencji open source. Na rynku wyszukiwarek umiejscawiany jest obok produktów takich jak Sphinx czy Katta. Długa lista użytkowników, do których należą takie firmy jak AOL, Disney, AT&T, Apple, Digg, LinkedIn, Buy.com, WhiteHouse.gov, potwierdza tylko jego popularność.

Lista cech i funkcjonalności jest bogata:

  • indeksowanie
    • indeksowanie dokumentów XML, CSV (również Word i PDF)
    • pełne i częściowe indeksowanie bezpośrednio z baz danych SQL
    • deduplikacja danych
    • synonimy
    • tokenizacja (usuwanie znaków specjalnych)
    • stemming (sprowadzanie do formy podstawowej)
  • wyszukiwanie
    • filtrowanie, sortowanie
    • podświetlanie trafień
    • liczniki
    • faceted search (grupowanie)
  • wieloplatformowość
  • skalowalność
  • replikacja

Solr napisany jest w Javie, jednak do jego używania nie jest konieczna znajomość tego języka programowania. Pełna obsługa, czyli wyszukiwanie, indeksowanie i modyfikacja danych odbywa się przy pomocy interfejsu HTTP/XML. Biblioteki dostępne są w dla wielu popularnych języków a dane wyjściowe mogą być zwracane w kilku formatach: XML/XSLT, JSON, Python, Ruby lub PHP.

Indeksowanie

Apache Solr opiera się na Lucene przez co charakterystyka indeksu oparta jest przede wszystkim na jej właściwościach. Indeks jest z założenia dzielony na pola i każde z nich mogą określać atrybuty:

  • Typ – wartość tego atrybutu określa jak przetwarzać pole
  • Indeksowane – jeśli pole jest indeksowane to można po nim przeszukiwać, sortować i zawężać
  • Przechowywane – pola z tym atrybutem pojawiają się w wynikach wyszukiwania
  • Kompresowane – dane w takich polach przechowywane są z kompresją gzip
  • Wielowartościowe – pole zawiera listę zamiast pojedynczej wartości

Ze względu na skuteczność wyników, bardzo istotny jest sam proces indeksowania danych – typy tekstowe podlegają serii transformacji: tokenizacji, stemmingowi, itp. Dla procesu wyszukiwania kluczowe jest aby kolejność tych operacji nie zniekształcała danych trafiających do indeksu. W taki sam sposób powinna być transformowana fraza podana przez użytkownika, wtedy następuje idealne dopasowanie poszczególnych tokenów z indeksu i zapytania.

Dużą przewagą Solra na tle innych rozwiązań jest funkcjonalność faceted search, przydatna szczególnie w rozwiązaniach e-commerce. Ogólnie mówiąc funkcja ta polega na grupowaniu wyników w kategorie i zawężaniu kolejnych wyszukiwań. W ten sposób tworzy się wirtualny katalog oparty nie na hierarchicznym drzewie, lecz na metadanych opisujących obiekty. Tłumacząc to na przykład produktów w sklepie internetowym, można je wyszukiwać po producencie, marce, zakresie cen, kolorze, czasie dostawy, ocenie itd. Kategoryzacja następuje automatycznie przez mechanizm wyszukiwarki, a funkcjonalność ta możne być rozszerzona przez dodanie liczników.

Testy wydajnościowe

Jednym z parametrów serwera wyszukiwania jest czas budowania indeksu. Dla testowego przypadku 11 mln rekordów transport z bazy danych i zaindeksowanie trwało kilkanaście godzin. Może się to wydawać dużo, ale należy pamiętać, że w typowych zastosowaniach ładowanie całościowe odbywa się tylko raz. Solr udostępnia bowiem funkcjonalność częściowych aktualizacji. Nie chodzi tutaj tylko o dodawanie danych, jak ma to miejsce w niektórych silnikach wyszukiwawczych, ale również o ich modyfikację i usuwanie.

Szczególnie interesowała nas wydajność w zależności od parametrów takich jak wielkość indeksu, czy opcje wyszukiwania. Testy wydajnościowe zostały przeprowadzone przy pomocy narzędzia Jmeter dla kilku konfiguracji sprzętowych. Źródłem danych testowych były realne oferty jednego z serwisów a wyszukiwane frazy zostały wybrane z listy najpopularniejszych zapytań.

Na początek wyniki testów na „standardowej” maszynie HP Proliant DL360 G4. Należy pamiętać, że nie można jej porównywać do PC-ta o podobnych parametrach :)

Maszyna: HP Proliant DL360 G4p
CPU: Xeon 3.2 GHz
Ilość CPU: 2 CPU x 2 core
RAM: 2GB

Parametry testu:
Opcja faceted search: tak
Xms: 512
Xmx: 1024
Threads: 10

Parametry xms i xmx dotyczą środowiska uruchomieniowego javy, natomiast parametr threads we wszystkich testach oznacza ilość równoległych połączeń symulowanych za pomocą narzędzia jmeter.

Zmierzone ilości odpowiedzi na sekundę dla dwóch przykładowych wielkości indeksu potwierdzają przypuszczenia, że wydajność zależy od wielkości indeksu. Należy zaznaczyć, że test został przeprowadzony dla „najcięższej” opcji wyszukiwania z wykorzystaniem opcji faceted search.

Po wstępnych testach przyszedł czas na wykorzystanie dużo mocniejszej maszyny czyli HP ProLiant DL380 G6 L5520 i porównanie wyników dla obu maszyn. Wszystkie kolejne testy zostały wykonane dla największego indeksu zawierającego 11 mln rekordów i zajmującego prawie 2GB.

Maszyna:
HP ProLiant DL380 G6 L5520
CPU: Xeon 2.27 GHz
Ilość CPU: 2 CPU x 4 core
RAM: 24GB

Parametry testu:
Ilość rekordów: 11mln
Wielkość indeksu: 1,9GB
Threads: 10

Z testów wynika, że opcja faceted search jest bardzo wymagająca i znacząco obniża wydajność. Należy zwrócić uwagę na wysoką wydajność, która dla tradycyjnych baz danych jest bardzo trudna do osiągnięcia.

Na koniec badanie granicy wydajności dla najmocniejszej maszyny i największego indeksu w zależności od ilości równoległych wątków.

Maszyna:
HP ProLiant DL380 G6 L5520
CPU: Xeon 2.27 GHz
Ilość CPU: 2 CPU x 4 core
RAM: 24GB

Parametry testu:
Xms: 16000
Xmx: 20000
Ilość rekordów: 11mln
Wielkość indeksu: 1,9GB

Na podstawie wyników można stwierdzić, że graniczną wartością dla podanej konfiguracji jest 500req/s. Dodatkowo wraz ze wzrostem obciążenia rośnie czas odpowiedzi. Najbardziej obciążonym elementem jest CPU. Solr wykorzystał całą dostępną pamięć RAM (24GB) mimo tego, że sam indeks miał „tylko” 2GB.

W przypadku gdy wydajność pojedynczej maszyny jest niewystarczająca, można zastosować architekturę, która będzie skalowalna dla wybranego przez nas parametru. Kiedy pojemność indeksu przekracza dostępną dla naszej maszyny pamięć operacyjną, Solr oferuje tzw. shardingindeksów, który polega na podzieleniu go na wiele instancji. Minusem tego rozwiązania jest znaczący spadek wydajności. Kolejnym poziomem, na którym możemy skalować system jest przepustowość wyszukiwania. Łatwy sposób na zwielokrotnienie wartości tego parametru polega na powieleniu maszyn i instancji wyszukiwarki. Dostępna w Solr replikacja indeksów może pomóc w stworzeniu takiej architektury.

Podsumowanie

Solr wywołuje pozytywne wrażenia. Rozbudowane funkcjonalności oraz wysoka wydajność może być wykorzystana w sytuacjach, gdy rozwiązania bazodanowe nie sprawdzają się. Przy określonych warunkach wydajność na jednej maszynie sięga nawet 1000 req/s co może zaspokoić potrzeby wymagających użytkowników. Dodatkowo te wartości można zwiększyć wykorzystując replikację i skalowalność. Serwer wyszukiwania pełnotekstowego Solr stanowi ciekawą alternatywę dla rozwiązań takich jak Sphinx czy Katta.

Rafał Kosturek
Projektant Systemów Informatycznych