Domyślne WooCommerce zwalnia, zanim katalog zrobi się ciekawy. Czysta instalacja z kilkuset produktami działa szybko na stagingu, a ten sam szablon z dziesiątkami tysięcy produktów i zamówień zaczyna mieć długi TTFB, cart fragments kolejkują się na archiwum sklepu, a tabela wp_options po cichu puchnie.
Problemem nie jest platforma, tylko konfiguracja i lata dokładania wtyczek. Jako programista WooCommerce na co dzień optymalizuję sklepy pod wydajność, a ten tekst to notatki z takich audytów.
To przewodnik terenowy po utwardzaniu WooCommerce pod realny ruch. Zakłada dostęp do shella, WP-CLI i gotowość do czytania slow query logu.
Na czym polega migracja WooCommerce do HPOS
Przez dekadę WooCommerce przechowywało zamówienia jako wpisy typu shop_order w wp_posts (ta sama tabela co artykuły na blogu), a każdą pozycję, adres i pole metadanych rozbijało na wiersze w wp_postmeta. Zapytanie “zamówienia z maja” oznaczało skanowanie tabeli wymieszanej z rewizjami, autozapisami i szkicami stron, a potem trzy lub cztery JOIN-y z postmeta, żeby odtworzyć każde zamówienie.
High Performance Order Storage przenosi zamówienia do tabel wc_orders, wc_order_addresses, wc_order_operational_data i wc_orders_meta. Listy zamówień trafiają bezpośrednio w indeksowane kolumny, zamiast składać każdy wiersz z postmeta.
HPOS jest domyślny dla nowych instalacji od WooCommerce 8.2, wydanego w październiku 2023, według dokumentacji HPOS. Sklepy uruchomione przed tą wersją często nadal działają na przechowywaniu w postach, dlatego migracja wciąż jest pierwszym punktem większości audytów.
Czego HPOS sam nie naprawi:
- Własne wtyczki, które zapisują dane w kluczach postmeta zamiast przez API zamówień, po wyłączeniu trybu zgodności po cichu się rozjadą
- Wtyczki, które czytają zamówienia przez
get_post_meta($order_id, ...)zamiast$order->get_meta(), zaczną zwracać puste wartości, gdy stara tabela przestanie być źródłem prawdy - Raporty zbudowane na
WP_Querypo typieshop_ordertrzeba przepisać
Przebieg:
- WooCommerce -> Ustawienia -> Zaawansowane -> Funkcje, włącz High Performance Order Storage z włączonym trybem zgodności
- Puść synchronizację poza godzinami szczytu; w dużym sklepie może trwać kilka godzin
- Sprawdź dane poleceniem
wp wc hpos verify_data - Przez tydzień testuj wszystkie wtyczki dotykające zamówień, z trybem zgodności nadal zapisującym do postmeta
- Wyłącz tryb zgodności dopiero, gdy potwierdzisz, że każda taka wtyczka czyta z HPOS
wp wc hpos status
wp wc hpos sync --batch-size=500
wp wc hpos verify_dataPolecenia WP-CLI dla HPOS od WooCommerce 8.9
Starsze poradniki używają przestrzeni wp wc cot. WooCommerce 8.9.0 oznaczyło ją jako przestarzałą: stare polecenia nadal działają, ale każde wypisuje ostrzeżenie z nazwą następcy w wp wc hpos, a verify_cot_data zmieniło nazwę na verify_data (CLIRunner.php). Dokumentacja narzędzi CLI dla HPOS i opisy samych poleceń podają obecny zestaw:
wp wc hpos statuspokazuje ustawienia HPOS i stan synchronizacjiwp wc hpos count_unmigratedliczy zamówienia, które czekają na synchronizacjęwp wc hpos syncmigruje zamówienia partiami, a--batch-sizedomyślnie wynosi 500wp wc hpos verify_dataporównuje oba magazyny danych; flaga--re-migrateponownie synchronizuje zamówienia z różnicami i może nadpisać zamówienie, więc najpierw użyj jej na staginguwp wc hpos diff 123pokazuje różnice dla jednego zamówieniawp wc hpos compatibility-mode enableidisableprzełączają synchronizację bez wchodzenia do paneluwp wc hpos cleanupusuwa stare dane z tabel postów dla zmigrowanych zamówień. Dokumentacja nazywa to operacją destrukcyjną i bez argumentów polecenie nic nie robi;wp wc hpos cleanup allprzetwarza wszystkie zamówienia
cleanup uruchamiaj dopiero wtedy, gdy tryb zgodności jest wyłączony na tyle długo, że żadna wtyczka nie czyta starej kopii, i zawsze po kopii zapasowej bazy.
Jak dostosować własną wtyczkę do HPOS
WooCommerce ostrzega właściciela sklepu, gdy ten próbuje włączyć HPOS przy aktywnej wtyczce zadeklarowanej jako niezgodna, i pokazuje to samo ostrzeżenie na ekranie wtyczek. Przy wtyczkach, które nie są rozszerzeniami WooCommerce, ostrzeżenie pojawia się tylko wtedy, gdy nagłówek wtyczki zawiera linię WC tested up to. Własna wtyczka deklaruje swój status w głównym pliku, tak jak pokazuje zbiór przepisów HPOS:
add_action( 'before_woocommerce_init', function() {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
} );Deklaracja to obietnica, a nie poprawka. Kod za nią musi ładować zamówienia przez wc_get_order() zamiast get_post() i zapisywać metadane przez obiekt zamówienia (update_meta_data(), add_meta_data(), delete_meta_data(), a potem save()) zamiast update_post_meta(). Wtedy WooCommerce samo decyduje, do których tabel trafia zapis. Dokumentacja zaznacza, że save() jest stosunkowo kosztowne, więc pętla zapisująca zamówienie po każdej zmianie metadanych sama staje się problemem wydajności. Kod, który musi rozróżniać silnik przechowywania, może wywołać OrderUtil::custom_orders_table_usage_is_enabled().
Jak wyłączyć cart fragments w WooCommerce
Starszy sklep WooCommerce albo taki z widżetem koszyka w nagłówku pokaże w GTmetrix lub WebPageTest żądanie ?wc-ajax=get_refreshed_fragments na każdej podstronie. To WooCommerce pyta PHP, czy ikonka koszyka w nagłówku się zmieniła: na stronie głównej, na blogu, w archiwach kategorii, na stronie “O nas”. Nawet gdy koszyk jest pusty.
Najprostsza reguła zakresu:
add_action( 'wp_enqueue_scripts', function() {
if ( is_cart() || is_checkout() || is_product() ) {
return;
}
wp_dequeue_script( 'wc-cart-fragments' );
}, 11 );Wtyczki Perfmatters i Asset CleanUp wystawiają to jako przełącznik w panelu. Obie drogi prowadzą do tego samego celu: cart fragments mają działać tylko tam, gdzie ikonka koszyka naprawdę musi aktualizować się na żywo.
Jeśli licznik koszyka w nagłówku jest potrzebny na każdej stronie, trzymaj go w localStorage i aktualizuj z JavaScriptu przy zdarzeniach dodania do koszyka, zamiast odpytywać serwer.
Kiedy WooCommerce ładuje cart fragments od wersji 7.8
WooCommerce 7.8 zmieniło zachowanie domyślne. Według wpisu na blogu deweloperskim WooCommerce Best practices for the use of the “cart fragments” API (16 czerwca 2023) skrypt nie jest już dołączany na każdej ścieżce sklepu. Nadal ładuje się w trzech przypadkach: na stronach, na których renderuje się widżet koszyka, gdy skrypt zewnętrzny rejestruje skrypt cart fragments jako zależność, oraz gdy kod dołącza go jawnie. Ten sam wpis zaznacza, że część motywów, w tym Storefront, ma widżet na stałe w szablonach.
W aktualnym sklepie to żądanie w wodospadzie jest więc objawem z konkretną przyczyną. Wyszukaj uchwyt wc-cart-fragments w źródle strony i sprawdź, który szablon motywu albo która wtyczka go dociąga. Wyłączenie skryptu bez tej kontroli może zepsuć koszyk w nagłówku, który motyw nadal odświeża przez fragments, a wtyczka deklarująca skrypt jako zależność i tak dołączy go ponownie.
Object cache czy transienty w bazie danych
WooCommerce intensywnie korzysta z transientów: zakresy cen wariantów, wyszukiwanie terminów atrybutów, obliczenia kosztów wysyłki. Bez object cache transienty trafiają do wp_options. To, czy ładują się przy każdym żądaniu, zależy od czasu wygaśnięcia: set_transient() zapisuje transient bez wygaśnięcia z autoload, a transient z wygaśnięciem bez autoload, plus osobny wiersz _transient_timeout_. WooCommerce zapisuje transienty cen wariantów i listy wariantów potomnych z 30-dniowym wygaśnięciem (magazyn danych produktów zmiennych), więc głównie zwiększają liczbę wierszy w wp_options. Ciężar autoload biorą na siebie opcje, które wtyczki zapisują bez wygaśnięcia.
Wybierz jeden backend cache i trzymaj się go. Albo Redis lub Memcached jako prawdziwy object cache, albo transienty w bazie. Mieszanie obu daje błędy unieważniania, które trudno zdiagnozować.
# Rozmiar autoload w wp_options
wp db query "SELECT SUM(LENGTH(option_value)) AS bytes, COUNT(*) AS rows FROM wp_options WHERE autoload IN ('yes', 'on', 'auto-on', 'auto');"
# Największe opcje z autoload
wp db query "SELECT option_name, LENGTH(option_value) AS bytes FROM wp_options WHERE autoload IN ('yes', 'on', 'auto-on', 'auto') ORDER BY bytes DESC LIMIT 20;"WordPress wykonuje wiele zapytań, żeby zbudować pojedynczą kartę produktu: warianty, ceny, stany magazynowe. Redis trzyma w RAM wyniki tych zapytań. Gdy Redis jest skonfigurowany na serwerze, u hostingu z zarządzanym Redisem albo na własnej instancji redis-server, a object-cache.php leży na miejscu, set_transient() zapisuje do object cache zamiast do wp_options, transienty przenoszą się do RAM i spada presja na autoload.
Wartości autoload w WordPress 6.6 i próg 800 KB
WordPress 6.6 zmienił sposób zapisu autoload. Notatka deweloperska rdzenia Options API: disabling autoload for large options wprowadza wartości on, off, auto, auto-on i auto-off; on i off to jawne decyzje, a auto-on i auto-off ustawia sam WordPress. Funkcja wp_autoload_values_to_autoload() zwraca yes, on, auto-on i auto, dlatego zapytania audytowe powyżej filtrują po tej liście. Zapytanie sprawdzające tylko autoload = 'yes' pomija każdą opcję zapisaną po aktualizacji i pokazuje sklep czystszym, niż jest.
Razem ze zmianą przyszły dwa progi. Opcja większa niż 150 000 bajtów nie jest ładowana automatycznie, chyba że kod jawnie o to poprosi, a filtr wp_max_autoloaded_option_size przesuwa ten limit. Kondycja witryny zgłasza problem, gdy łączny rozmiar opcji z autoload przekracza 800 KB. To najtańszy pierwszy test w nieznanym sklepie, bo nie wymaga dostępu do shella i nazywa problem, zanim ktokolwiek otworzy klienta bazy danych.
Czego nie wolno cache’ować w sklepie WooCommerce
Cache statyczny pomaga archiwom, kartom produktów i wpisom na blogu. Psuje wszystko, co zależy od sesji użytkownika, bo każdy klient ma własny koszyk.
Obowiązkowe wyjątki dla każdego cache stron i każdej reguły Cloudflare:
/koszyk/lub/cart//zamowienie/lub/checkout//moje-konto/lub/my-account/- Każdy URL z
?wc-ajax= - Każde żądanie z cookie
woocommerce_items_in_cart - Endpointy REST pod
/wp-json/wc/
Statyczne zasoby (zdjęcia, CSS, JS) cache’uj na krawędzi sieci. Cloudflare APO for WordPress potrafi cache’ować także HTML dla niezalogowanych i respektuje cookies sesji WooCommerce, jeśli jest dobrze skonfigurowane, ale sprawdź curl -I na koszyku i zamówieniu, czy dostajesz cf-cache-status: BYPASS. Źle ustawiony cache, który pokazuje koszyk innego klienta, to incydent z zakresu RODO, a nie zysk wydajności.
Zapytania o produkty zmienne i filtr woocommerce_variable_children_args
Produkty zmienne z kilkudziesięcioma wariantami każdy mnożą JOIN-y. Archiwum sklepu odzieżowego z 200 produktami zmiennymi po 30 wariantów to przy każdym wczytaniu JOIN z wp_posts po 6000 produktów potomnych.
Dwie praktyczne poprawki:
- Ogranicz warianty ładowane do listy rozwijanej do tych, które są na stanie i widoczne
- Użyj
woocommerce_variable_children_args, aby na archiwach wykluczyć z pierwszego ładowania warianty prywatne i niedostępne
add_filter( 'woocommerce_variable_children_args', function( $args ) {
if ( is_shop() || is_product_category() ) {
$args['post_status'] = 'publish';
$args['meta_query'][] = array(
'key' => '_stock_status',
'value' => 'instock',
);
}
return $args;
} );Jak ograniczyć rozrost tabel Action Scheduler
Każde rozszerzenie WooCommerce, które pracuje w tle, korzysta z Action Scheduler. Subskrypcje, maile przypominające, odzyskiwanie porzuconych koszyków, synchronizacja stanów, integracje z ERP: wszystko ląduje w wp_actionscheduler_actions i wp_actionscheduler_logs.
W sklepie z aktywnymi subskrypcjami i odzyskiwaniem koszyków te tabele potrafią w ciągu roku zebrać ogromną liczbę zakończonych i nieudanych akcji, a panel odpytuje je przy każdym wczytaniu, żeby pokazać licznik kolejki.
Skrypt konserwacyjny:
# Usuń zakończone i anulowane akcje starsze niż 31 dni
wp action-scheduler clean --before="31 days ago" --pause=1
# Sprawdź rozmiar kolejki
wp db query "SELECT status, COUNT(*) FROM wp_actionscheduler_actions GROUP BY status;"
# Sprawdź indeksy na status i scheduled_date_gmt
wp db query "SHOW INDEX FROM wp_actionscheduler_actions;"Jak długo Action Scheduler przechowuje zakończone i nieudane akcje
Action Scheduler sprząta po sobie podczas przebiegu kolejki. Jego mechanizm czyszczenia kolejki usuwa zakończone i anulowane akcje starsze niż 31 dni, a filtr action_scheduler_retention_period zmienia to okno. Od Action Scheduler 4.0 usuwane są także akcje nieudane, domyślnie po trzech miesiącach (action_scheduler_retention_period_for_failed); komentarz w kodzie wiąże ten okres z kwartalnym cyklem księgowym.
Czyszczenie działa wewnątrz procesu kolejki. W sklepie, który wyłącza WP-Cron i nie ma systemowego crona wywołującego wp-cron.php albo wp action-scheduler run, kolejka staje, a razem z nią czyszczenie, bez żadnego błędu na ekranie. Zaległości po takiej przerwie usuniesz ręcznie przez wp action-scheduler clean, które według dokumentacji WP-CLI Action Scheduler przyjmuje --status (domyślnie canceled,complete), --before (domyślnie 31 dni), --batch-size (domyślnie 20) i --pause, czyli przerwę między partiami na obciążonej bazie.
Jak zoptymalizować zdjęcia produktów w WooCommerce
Zdjęcia produktów to zwykle najcięższa część każdego sklepu. Trzy zasady:
- AVIF dla zdjęć głównych i galerii, z WebP jako zapasem dla starszych wersji Safari, które wciąż pojawiają się w ruchu
- Nie wgrywaj surowych zdjęć po 4000 px. Ogranicz proces wgrywania do 2000 px na dłuższym boku
- Natywne
loading="lazy"wystarcza; usuń stare skrypty JS do leniwego ładowania, które z nim kolidują
Zmniejszaj zdjęcia przed wgraniem, zamiast liczyć, że WordPress wygeneruje miniatury w locie, bo to zapisuje dane w wp_postmeta i powiększa bazę.
Jak wyczyścić bazę danych WooCommerce przez WP-CLI
Uruchamiaj to co miesiąc, częściej w sklepach z dużą liczbą porzuconych koszyków:
# Usuń wygasłe sesje (potrzebne tylko, gdy zaplanowane czyszczenie stanęło)
wp db query "DELETE FROM wp_woocommerce_sessions WHERE session_expiry < UNIX_TIMESTAMP();"
# Wyczyść transienty WooCommerce
wp wc tool run clear_transients --user=1
# Zoptymalizuj tabele
wp db optimize
# Sprawdź głębokość kolejki Action Scheduler
wp action-scheduler statusPlanuj to przez systemowy cron, a nie wp-cron.php, który odpala się tylko przy ruchu. Flaga --user przy wp wc tool run pochodzi z przykładów WooCommerce CLI; podaj ID konta administratora w swojej instalacji. Kto woli panel, może użyć WP-Optimize.
Jak WooCommerce czyści sesje klientów
WooCommerce samo przycina tabelę sesji. Rejestruje cykliczną akcję Action Scheduler woocommerce_cleanup_sessions, uruchamianą co 12 godzin (class-woocommerce.php), a obsługa sesji usuwa wygasłe wiersze partiami po 100, z krótką przerwą między partiami. Sesja gościa wygasa po dwóch dniach, a zalogowanego klienta po siedmiu; filtry wc_session_expiration i wc_session_expiring zmieniają oba okresy. Czas życia dłuższy niż 30 dni zostawia ostrzeżenie w logu WooCommerce, bo dłuższe sesje powiększają tabelę.
Wynikają z tego dwie rzeczy. Tabela sesji licząca gigabajty zwykle oznacza, że kolejka Action Scheduler nie działa albo wtyczka wydłużyła czas życia sesji, więc przed kasowaniem czegokolwiek sprawdź wp action-scheduler status i te filtry. I nigdy nie uruchamiaj TRUNCATE na wp_woocommerce_sessions w działającym sklepie: opróżnia to wszystkie aktywne koszyki, a DELETE ... WHERE session_expiry < UNIX_TIMESTAMP() powyżej usuwa tylko wiersze, które już wygasły.
Jakie metryki wydajności WooCommerce śledzić
Optymalizacja na ślepo kończy się optymalizowaniem nie tego, co trzeba. Wybierz kilka sygnałów i sprawdzaj je co tydzień:
- TTFB przy zimnym cache na archiwum sklepu i jednej karcie produktu
- Czas do pierwszego bajtu na koszyku i zamówieniu z jednym i czterema produktami w koszyku
- Liczba wierszy i łączny rozmiar opcji z autoload w wp_options
- Głębokość kolejki Action Scheduler i najstarsza oczekująca akcja
Query Monitor na stagingu pokazuje, które zapytania dominują. New Relic albo Datadog APM na produkcji pokazują rzeczywisty rozkład. PageSpeed Insights to test dymny, a nie diagnoza.
Ostatnia aktualizacja
2026-10-14. Jeśli twój sklep nie pasuje do tych wzorców, to nie wzorce są problemem. Zacznij od slow query logu. Konfigurację HPOS, Redisa i porządków w bazie najszybciej domknie programista WooCommerce, który zna te wąskie gardła z produkcji.
Potrzebujesz wsparcia? Sprawdź cennik stron i sklepów WordPress, aby zlecić nam optymalizację sklepu.







