6 grzechów głównych w kontekście zadawania zapytań

W swojej dotychczasowej pracy związanej z Lucene i Solr spotkałem się z różnymi zapytaniami. O ile w przypadku Lucene programista z reguły wie co chce osiągnąć i zastanawia się nad optymalnym rozwiązaniem, o tyle w przypadku Solr już tak nie jest. Solr jest produktem z którego teoretycznie może skorzystać każdy, zarówno osoba nie znająca języka Java, taka, która nie posiada szerokiej i specjalistycznej wiedzy technicznej, jak również programista. Właśnie ze względu na to, że Solr jest produktem, który bardzo łatwo uruchomić i z niego skorzystać, wiele osób nie zadaje sobie trudu związanego z przeczytaniem dokumentacji, czy przejrzeniem listy dyskusyjnej użytkowników. Co za tym idzie, ludzie Ci, wcześniej czy później popełniają błędy – błędy wynikające z różnych braków – braku wiedzy na temat Solr, umiejętności, doświadczenia, czy ze zwykłego braku czasu i napiętych terminów. Chciałbym dzisiaj przedstawić kilka podstawowych błędów przy składaniu zapytań i jak ich uniknąć.

1. Brak wykorzystania filtrów

Jednym z podstawowych błędów jakie spotykam co jakiś czas jest brak wykorzystania filtrów, czyli prosto mówiąc brak wykorzystania parametru fq w zapytaniach. Pamiętajmy o tym, filtry to nasi przyjaciele 😉 Dzięki filtrom cache wykorzystywany jest bardziej optymalnie. Filtry nie wpływają na ważność dokumentu w kontekście zapytania (współczynnik score), a co za tym idzie, możemy wykonywać zawężania bez obawy o zmianę wartości score poszczególnych dokumentów (przydatne np. w sklepach e-commerce w przypadku zawężania grup produktów).

2. Warunki logiczne i parametr q

Kolejny z „grzechów” jakie spotykam dość często, dość mocno związany z poprzednim punktem. Nie jest to może błąd w dosłownym tego słowa znaczeniu, aczkolwiek, jest to obszar, gdzie prosta zmiana będzie miała spory wpływ na wydajność. Zakładając, że domyślnym operatorem logicznym jest OR, wyobraźmy sobie zapytanie w postaci q=(java+wzorce+projektowe)+AND+kategoria:ksiazki+AND+promocja:true+AND+wydawnictwo:ABC. Zapytanie to jest jak najbardziej poprawne z punktu widzenia logiki aplikacji, gdzie mamy dostać odpowiednią grupę wyników wyszukiwania. Co jednak, jeżeli chcemy, aby także optymalnie wykorzystywało cache Solr, a tym samym wykonywało się szybciej. Odpowiedź jest dość prosta – należy przenieść niektóre z warunków do filtrów. Zmieniając przedstawione zapytanie na q=java+wzrce+projektowe&fq=kategoria:ksiazki&fq=promocja:true&fq=wydawnictwo:ABC Solr skorzysta z dwóch rodzajów cache – queryDocumentCache w celu pobrania dokumentów dla zapytania z parametru q oraz z filterCache dla każdego z filtrów. Zmiana zapytania w pokazany sposób pozwoliła na wykorzystanie dodatkowego cache oraz na uporządkowanie wpisów w queryDocumentCache (ze względu na skrócenie zapytania w parametrze q).

3. Ogromne ilości facet query

Kolejny „grzech” związany z obsługą grup dokumentów. Dość często, szczególnie, w przypadku aplikacji które mają dużą ilość parametrów pozwalających kategoryzować produkty spotykałem zapytania z dużą ilością parametrów facet.query. Zapytania te używane były do wyświetlania grup dokumentów – według ceny, lokalizacji, grup i tak dalej. Dobrym przykładem jest grupowanie po cenie, gdzie klient biznesowy może określać przedziały cenowe dla poszczególnych kategorii i na tym podstawie grupować produkty. Pamiętajmy, że dołożenie do zapytania 100, czy 200 razy parametru facet.query odbija się na wydajności i to czasami dość znacznie. Jeżeli interesuje nas szybka reakcja Solr nie możemy stosować takich zapytań. W takich wypadkach zawsze proponuję modyfikację struktury indeksu, czyli stworzenie odpowiednich przedziałów w importerze aplikacji i przekazywanie do Solr identyfikatorów tych przedziałów, które tłumaczy aplikacja. Pozwala to na zlikwidowanie dziesiątek, czy setek facet.query na rzecz jednego parametru facet, po odpowiednim polu (oczywiście w przykładzie z grupami zależnymi od kategorii mogą to być pola dynamiczne). Wiąże się z jeszcze jedną niedogodnością – wytłumaczeniem klientowi, dlaczego musi nacisnąć przycisk reindeksacji danych po zmianach przedziałów. Z reguły jednak testy wydajnościowe przy dużym obciążeniu i dużej różnorodności zapytań mówią same za siebie.

4. Limity facetingu

Problem pojawiający się na styku zapytań zadawanych do Solr, a logiki biznesowej jaką realizować ma aplikacja korzystająca z Solr. Przykładem tego „grzechu” jest prosta lista kategorii, którą klient chce mieć wyświetlaną w zależności od strony na jakiej znajduje się użytkownik. Kiedy kategorii jest mało nie mamy problemu, gorzej kiedy tych kategorii jest bardzo dużo. Bardzo często spotykałem się z podejściem ze strony programistów, aby pobierać wszystkie kategorie z Solr (z mocno zwiększonym w stosunku do domyślnego parametrem facet.limit) i dopiero w aplikacji zawężać te wyniki. Według mnie jest to podejście, które może generować problemy – po pierwsze faceting wymaga pamięci, po drugie czasu na przetworzenie i agregację wyników. Co więcej, pobranie wszystkich 50.000 kategorii wraz z licznościami może być bolesne dla Solr. Jeżeli zależy nam na szybkich zapytaniach, starajmy się korzystać z parametru facet.limit rozsądnie i ewentualnie tak budować aplikację, aby możliwe było stronicowanie wyników facetingu i korzystanie tym samym z parametru facet.offset. Jeżeli nie jest to możliwe, to przynajmniej skonfigurujmy tak kontener w którym działa Solr, aby miał wystarczającą ilość pamięci, aby obsłużyć równoległe zapytania i przygotujmy się, że zapytania z dużą wartością facet.limit mogą wykonywać się dłużej, niż inne.

5. Pobieranie niepotrzebnych danych

Bardzo często spotykanym problemem jest pobieranie wszystkich informacji, a nie tylko tych, które są nam potrzebne. Oczywiście problem nie dotyczy wdrożeń, gdzie Solr serwuje informacje takie jak na przykład identyfikator produktu i tylko identyfikator. Jednak, duża ilość wdrożeń z którą miałem do czynienia opierała się prawie w całości na Solr, a co za tym idzie indeks składał się z wielu pól z atrybutem stored ustawionym na wartość true. Programiści korzystający z Solr bardzo rzadko korzystali z parametru fl oraz możliwości ograniczania pól, które są zwracane odpowiedzi. W ekstremalnych przypadkach prowadziło to do problemów z ilością danych, jakie trzeba było przesyłać przez sieć.

6. Wiele zapytań do uzyskania liczności grup dokumentów

W niektórych wdrożeniach ważniejsze od standardowego wyszukiwania, gdzie użytkownik wpisuje frazę jaką chce znaleźć, jest przechodzenie do dokumentów za pomocą nawigacji, na przykład przy pomocy działów, kategorii, podkategorii i tak dalej. Bardzo często oprócz na przykład nazwa kategorii podaje się także informacje takie jak ilość dokumentów w tej kategorii, czyli np. produktów. Spotkałem się z przypadkami, gdzie ilości dokumentów w poszczególnych kategoriach były pobierane za pomocą oddzielnych zapytań. Skutek – wyświetlenie 100 kategorii na formatce skutkowało taką samą ilością zapytań do Solr. Nie róbmy tego – jeżeli trzeba zmodyfikujmy indeks Solr tak, aby możliwe było wykorzystanie mechanizmów facetingu. Może w danym momencie będzie to więcej pracy, ale na pewno w dłuższej perspektywie czasu się to opłaci.

Kilka słów na koniec

Należy pamiętać, że są to tylko przykłady, które uważam za dość powszechne, a przynajmniej na które dość często natknąłem się podczas pracy. Nie są to na pewno wszystkie błędy popełniane przy korzystaniu z Solr, jednak mam nadzieję, że przynajmniej w pewnym stopniu uwypuklają stronę w którą należy spoglądać generując zapytania do Solr, czy optymalizując już istniejące.

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