Wyszukiwarka WooCommerce jest powolna. Nie dlatego, że ktoś źle ją napisał - po prostu tak działa WordPress. Każde wpisanie litery w pole szukajki odpala cały silnik: wtyczki, motywy, hooki, tłumaczenia, sesje. Zanim WordPress dotknie bazy danych z Twoim zapytaniem, minęło już 100-300 milisekund.
Dla autocomplete, gdzie użytkownik wpisuje literę co 50-150 ms, to wieczność.
Od jakiegoś czasu eksperymentuję z alternatywnym podejściem: RediSearch jako silnik wyszukiwania + SHORTINIT jako ultraszybki bootstrap WordPressa. Customowa wtyczka pisana od zera. Efekty? Mediana autocomplete na tanim VPSie za kilkadziesiąt złotych: 54 ms pełny round-trip. Sam Redis odpowiada w mniej niż 10 ms.
W tym artykule pokażę co udało mi się osiągnąć, jak to działa i dlaczego uważam, że to kierunek wart eksploracji.
Spis treści
Rozwiń spis treści
Dlaczego domyślna wyszukiwarka WooCommerce jest wolna?
Zacznijmy od tego, co właściwie dzieje się, kiedy klient wpisuje coś w pole wyszukiwania Twojego sklepu.
Standardowy request WordPress wygląda mniej więcej tak:
- PHP ładuje
wp-config.php - Ładuje wszystkie aktywne wtyczki (nawet te, które nie mają nic wspólnego z wyszukiwaniem)
- Ładuje motyw ze wszystkimi hookami
- Inicjalizuje tłumaczenia, sesje, uprawnienia
- Dopiero teraz odpala zapytanie SQL do bazy danych
A to zapytanie? Domyślnie WooCommerce szuka po tytułach i treści postów za pomocą LIKE '%szukana_fraza%'. MySQL nie ma jak tego zoptymalizować - musi przeskanować każdy wiersz w tabeli.
Efekt: 30-50 MB RAM i kilkaset milisekund zanim Twój klient zobaczy pierwszą podpowiedź.
Pluginy takie jak FiboSearch czy SearchWP rozwiązują część tego problemu (FiboSearch Pro używa wewnętrznie SHORTINIT), ale żaden z popularnych pluginów nie wykorzystuje RediSearch jako silnika full-text search.
RediSearch - co to jest i czemu warto?
Redis to baza danych typu klucz-wartość, która trzyma wszystko w pamięci RAM. Jest powszechnie używana w WordPressie jako cache dla wp_options i sesji.
RediSearch to moduł Redis, który dodaje pełnotekstowe wyszukiwanie. Nie jest to osobna baza danych - to rozszerzenie Redis, które pozwala na tworzenie indeksów, wyszukiwanie po początkach słów i łapanie literówek.
Czemu to istotne? Bo Redis operuje na RAMie i odpowiada w mikrosekundach. W moim teście na indeksie 2 500 produktów WooCommerce, typowy czas odpowiedzi FT.SEARCH to 2-5 ms per query. Praktycznie zawsze poniżej 10 ms.
Porównaj to z MySQL LIKE, który na tej samej liczbie produktów potrafi zabrać 50-200 ms.
SHORTINIT - WordPress bez WordPressa
Tu zaczyna się najciekawsza część eksperymentu.
WordPress ma wbudowaną stałą SHORTINIT, o której mało kto wie. Kiedy ustawisz ją na true przed załadowaniem wp-settings.php, WordPress ładuje absolutne minimum:
wp-config.php(dane połączenia z bazą)$wpdb(obiekt bazy danych)- Podstawowe stałe (
ABSPATH,WPINC)
I to tyle. Zero wtyczek. Zero motywów. Zero hooków. Zero tłumaczeń.
Zamiast 30-50 MB RAM i 100-300 ms bootstrapu, mamy ~5-10 MB i mniej niż 5 ms do pierwszej linii naszej logiki. To oznacza, że endpoint autocomplete uruchamia się szybciej niż WordPress zdążyłby załadować listę aktywnych wtyczek.
Ale jest haczyk
SHORTINIT = brak dostępu do wp_options, get_option() i w zasadzie wszystkich funkcji WordPressa poza gołym $wpdb.
Jak sobie z tym radzę? Ustawienia pluginu (host Redis, port, limity, strategia wyszukiwania) są zapisywane do auto-generowanego pliku PHP z define(). Klasa konfiguracyjna rozpoznaje w jakim trybie się uruchomiła i wybiera jeden z dwóch rozłącznych światów: jeśli istnieje stała MERIDA_SEARCH_REDIS_HOST - znaczy, że jesteśmy w SHORTINIT i cała konfiguracja leci z constów (early return). Dopiero gdy stałych nie ma, sprawdza czy get_option() w ogóle istnieje i wtedy czyta z bazy.
Albo jedno, albo drugie - nigdy mix. Niestandardowe podejście, ale działa zaskakująco dobrze.
Benchmarki z taniego VPSa
Całość testowałem na tanim VPSie z procesorem ~2 GHz. Celowo nie na rakiecie - chciałem zobaczyć jak to wygląda w realistycznych warunkach sklepu, który nie wydaje fortuny na hosting.
Pierwsze obserwacje
Zastrzeżenie: to są wyrywkowe requesty z DevTools, nie pełny benchmark. Pełne testy wydajnościowe planuję dopiero po potwierdzeniu usability - czyli po sprawdzeniu, że wyniki wyszukiwania faktycznie mają sens dla użytkownika. Na razie testuję czy architektura się trzyma.
Co widzę na tym etapie? Mediana czasu odpowiedzi autocomplete (pełny cykl: klient, serwer, Redis, odpowiedź) to okolice 50-60 ms. ~80% requestów poniżej 90 ms. Sam Redis odpowiada praktycznie zawsze poniżej 10 ms - wąskim gardłem jest sieć, nie aplikacja.
Trzy pomysły, które zrobiły różnicę
Nie chcę robić z tego pełnego tutoriala (jeszcze nie teraz), ale parę konceptów warto zasygnalizować, bo mogą Ci się przydać nawet w innym kontekście.
Najpierw dokładnie, potem luźniej
Zamiast od razu odpalać fuzzy search (który jest wolniejszy i zbyt liberalny - “mydło” fuzzy-matchuje “masło”), stosuję trzy przejścia:
- Dokładne dopasowanie -
suszarka*- szukaj słów zaczynających się od wpisanej frazy. Najszybsze i najcelniejsze. - Odchudzenie zapytania - usunięcie słów, które nic nie wnoszą (“do”, “na”, “z”) i ponowne szukanie
- Łapanie literówek -
%suszarka%- dopuszcza drobne błędy w pisowni, odpala się TYLKO gdy wcześniejsze przejścia nic nie zwróciły
Kluczowa zasada: jeśli dokładne dopasowanie daje wyniki, łapanie literówek nigdy się nie odpala. Zero zbędnej pracy.
Podwójna normalizacja polskich znaków
Tytuł jest indeksowany podwójnie: z diakrytykami (Suszarka do rąk) i bez (Suszarka do rak). Dzięki temu użytkownik wpisujący “rak” matchuje “rąk”. W polskim e-commerce to konieczność - klienci notorycznie pomijają polskie znaki w wyszukiwarkach.
Korekta kolejności wyników
RediSearch sortuje wyniki po tym, jak dobrze pasują do zapytania tekstowo. Ale nie wie nic o kontekście sklepu. Dlatego po odpowiedzi z Redisa, PHP nakłada korekty: dokładne trafienie w numer katalogowy (SKU) ląduje na górze, produkty niedostępne spadają w rankingu, promowane idą wyżej, a tytuł zaczynający się od szukanej frazy dostaje bonus.
Redis zwraca 5x więcej kandydatów niż potrzeba, PHP przelicza score i przycina do limitu.
Kiedy to ma sens?
Bądźmy szczerzy - dla 90% sklepów WooCommerce to overkill. Jeśli masz 200 produktów i kilkudziesięciu użytkowników dziennie, FiboSearch w wersji darmowej lub pro załatwi sprawę.
To podejście zaczyna mieć sens, gdy:
- Masz tysiące produktów i szukasz poniżej 100 ms round-trip
- Masz własny serwer (VPS/dedyk), na którym możesz zainstalować moduł RediSearch
- Chcesz pełną kontrolę nad logiką wyszukiwania (synonimy, wagi pól, re-ranking)
- Zależy Ci na lekkości - endpoint autocomplete zużywa ~5-10 MB RAM zamiast 30-50 MB
Jeśli Twój sklep stoi na współdzielonym hostingu - zapomnij. RediSearch wymaga dostępu do serwera na poziomie root.
Co dalej?
To dopiero początek eksploracji. W planach mam:
- Dokładne testy jakości wyników wyszukiwania - bo szybkość bez trafności nie ma sensu
- Testy wydajnościowe pod dużym obciążeniem (wielu użytkowników jednocześnie, większe indeksy)
- Jeśli wtyczka trafi na produkcję - pełne case study z realnymi danymi
Jeśli temat Cię zainteresował, chcesz pogadać o WooCommerce albo masz pytania - znajdziesz mnie na LinkedIn. Możesz też zostawić komentarz pod tym postem.
Zajmuję się na co dzień architekturą wydajności dla sklepów WooCommerce w ramach SHIFT64. Jeśli Twój sklep mógłby działać szybciej - zajrzyj, może będziemy mogli sobie pomóc.