sysadmin.ecommerce > php-optymalizacja-log-199-log-199-prestashop-baza-danych-zaczyna-generowac-w.md
root@prod-01:~/blog# cat php-optymalizacja-log-199-log-199-prestashop-baza-danych-zaczyna-generowac-w.md
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Data: 2025-06-16 | Kategoria: PHP & Optymalizacja | Czas czytania: 4 min
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

100% CPU w PrestaShop? Zanim dokupisz mocniejszy VPS, zrób to (Case Study)

###02

Większość właścicieli sklepów na platformie PrestaShop w momencie, gdy baza danych zaczyna generować wysokie zużycie procesora (CPU: 100%), decyduje się na bezrefleksyjne dokupienie mocniejszego VPS-a. To błąd rzemieślniczy.

Struktura bazy danych PrestaShop – ze względu na rozbicie cech produktów, atrybutów, kombinacji oraz multisklepowości na osobne relacje – z natury generuje potężne, wielopoziomowe zapytania JOIN. Jeśli baza nie posiada odpowiednich indeksów, każdy klient filtrujący produkty w sklepie zmusza silnik MariaDB do pełnego skanowania dysku (Full Table Scan).

Poniżej znajduje się zapis realnej ścieżki diagnostycznej i naprawczej na serwerze produkcyjnym, gdzie TTFB kategorii produktów wynosiło ponad 2.4 sekundy.

01 · Diagnoza z terminala (The Symptom)

Analiza za pomocą narzędzia htop wykazała permanentne wysokie utylizowanie wątków przez proces mariadbd. Pierwszym krokiem było uruchomienie logowania wolnych zapytań (Slow Query Log) bezpośrednio z poziomu CLI, aby namierzyć winowajcę.

Bash

# Włączenie logowania wolnych zapytań w locie (bez restartu usługi)
mysql -u root -p -e "SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1.0;"

Po kilkunastu minutach w logu /var/log/mysql/mariadb-slow.log pojawił się powtarzalny schemat – zapytanie generowane przez moduł warstwowego filtrowania (Faceted Search), które wykonywało się aż 1.82 sekundy:

SQL

# Time: 260615 14:22:11
# User@Host: prestadb[prestadb] @ localhost []
# Query_time: 1.824102  Lock_time: 0.000121 Rows_sent: 48  Rows_examined: 1420540
SELECT p.id_product, fp.id_feature_value 
FROM ps_product p
LEFT JOIN ps_feature_product fp ON (p.id_product = fp.id_product)
LEFT JOIN ps_category_product cp ON (p.id_product = cp.id_product)
WHERE cp.id_category = 42 AND fp.id_feature = 5
ORDER BY p.id_product DESC LIMIT 48;

Zwróć uwagę na parametr Rows_examined: 1 420 540. Aby zwrócić zaledwie 48 produktów na stronę, MariaDB musiała przeszukać i porównać w pamięci ponad 1.4 miliona rekordów.

02 · Analiza struktury (The Explain)

Użycie klauzuli EXPLAIN przed zapytaniem natychmiast obnażyło brak optymalizacji po stronie bazy danych:

SQL

EXPLAIN SELECT p.id_product, fp.id_feature_value FROM ps_product p ...
tabletypepossible_keyskeykey_lenrefrowsExtra
fpALLPRIMARYNULLNULLNULL842100Using where; Using temporary; Using filesort
peq_refPRIMARYPRIMARY4fp.id_product1Using index
cprefPRIMARYPRIMARY4fp.id_product1Using where

Kluczowy jest wiersz pierwszy: tabela ps_feature_product (fp) zwraca typ połączenia ALL (Full Table Scan), a pole key ma wartość NULL. Baza danych nie użyła żadnego indeksu dla tabeli łączącej produkty z ich cechami.

03 · Wdrożony Fix (The Solution)

PrestaShop domyślnie zakłada indeksy na klucze główne, ale bardzo często pomija indeksy kompozytowe (wielokolumnowe), które są niezbędne przy skomplikowanych operacjach JOIN z warunkami WHERE.

Rozwiązaniem było nałożenie indeksów na kolumny, po których następuje stałe mapowanie i filtrowanie danych:

SQL

-- Dodanie indeksu kompozytowego na tabelę cech produktów
ALTER TABLE ps_feature_product ADD INDEX idx_product_feature (id_product, id_feature);

-- Dodanie indeksu na tabelę kategorii (w celu przyspieszenia filtrowania wewnątrz kategorii)
ALTER TABLE ps_category_product ADD INDEX idx_category_product (id_category, id_product);

-- Wymuszenie odświeżenia statystyk optimizera MariaDB
ANALYZE TABLE ps_feature_product, ps_category_product, ps_product;

04 · Wynik liczbowy (Data-Driven Proof)

Po wdrożeniu zmian i ponownym wykonaniu testu EXPLAIN, typ połączenia zmienił się z ALL na ref / range, a baza danych zaczęła prawidłowo utylizować nowo utworzone klucze (idx_product_feature).

Plaintext

Przed optymalizacją:
● Rows examined: 1 420 540
● Czas wykonania zapytania SQL: 1.82 s
● Średni TTFB podstrony kategorii: 2420 ms

Po wdrożeniu indeksów:
● Rows examined: 214
● Czas wykonania zapytania SQL: 0.002 s
● Średni TTFB podstrony kategorii: 112 ms

Wnioski operacyjne: Narzut na procesor serwera spadł o 78%. Sklep odzyskał stabilność bez wydawania ani jednej złotówki na wyższy pakiet hostingowy czy mocniejszą maszynę w chmurze.

Plaintext

// koniec_logu

Zauważyłeś podobne symptomy? Jeśli Twój panel administracyjny PrestaShop ładuje się w nieskończoność, a klienci czekają sekundy na odświeżenie filtrów w sklepie – baza danych prawdopodobnie dławi się na nieoptymalnych zapytaniach.

[ → Prześlij parametry serwera do darmowego audytu zerowego ]

← Powrot do wszystkich artykulow

// alert_systemowy

Widzisz podobne symptomy na swoim serwerze e-commerce? Nie czekaj na awarię w szczycie ruchu.

→ Przejdź do formularza i zgłoś serwer do audytu zerowego