Prodavnica ti je prvih par meseci radila kao sat. Onda si jednog jutra otvorio spisak porudžbina i čekao pet sekundi da se učita. Pretraga po imenu kupca traje još duže. Filter po statusu ume da vrati 504. Frontend je i dalje pristojan, jer ga cache spasava, ali admin je postao mesto na koje ne ideš rado.
To se ne dešava zato što si nešto pokvario. Dešava se zato što je WordPress do skoro čuvao porudžbine na mestu koje za njih nikada nije bilo predviđeno. Ako imaš preko nekoliko hiljada porudžbina, ovo je verovatno tvoj problem, a rešenje se zove HPOS.
Gde su ti porudžbine zapravo smeštene
U klasičnom WooCommerce-u porudžbina nije poseban tip podatka. Ona je običan post u tabeli wp_posts, isto kao članak na blogu ili stranica. Sve ostalo, adresa za dostavu, način plaćanja, iznos poreza, valuta, ID kupca, transakcijski broj, ide u wp_postmeta kao gomila zasebnih redova.
Koliko redova? Po merenjima na tipičnim prodavnicama, jedna porudžbina ostavi za sobom oko 40 redova u wp_postmeta. Ako prodaješ 50 porudžbina dnevno, to je oko 72.000 novih redova mesečno, samo od porudžbina. Posle dve godine imaš tabelu sa nekoliko miliona redova, u kojoj su porudžbine izmešane sa metapodacima svih tvojih stranica, proizvoda i članaka.
Problem je u tome kako se ti podaci čitaju. Da bi ti prikazao spisak od dvadeset porudžbina sa imenom kupca, iznosom i statusom, WooCommerce mora da uradi seriju JOIN operacija nad tom ogromnom tabelom. Svaka kolona koju vidiš u spisku je jedan dodatni skok u wp_postmeta. Kad tabela naraste, upit koji je ranije trajao 80 milisekundi počne da traje tri sekunde, pa deset.
U praksi to izgleda ovako: ispod par hiljada porudžbina ne primetiš ništa, oko pet hiljada počne da smeta, preko deset hiljada admin postane neupotrebljiv u špicu.
Kako da proveriš da je problem baš u porudžbinama
Pre nego što bilo šta menjaš, izmeri. Jednostavan test: uporedi koliko se učitava /wp-admin/edit.php?post_type=product i koliko /wp-admin/admin.php?page=wc-orders ili stara adresa spiska porudžbina. Ako se proizvodi učitaju za sekundu, a porudžbine za osam, znaš gde je usko grlo.
Drugi test je još precizniji. Instaliraj Query Monitor i otvori spisak porudžbina. Ako u kartici Queries vidiš jedan upit koji sam pojede većinu vremena i u njemu se pominju postmeta i više LEFT JOIN naredbi, dijagnoza je gotova.
Ako se ispostavi da je sve podjednako sporo, i proizvodi i porudžbine i frontend, onda ovo nije tvoj problem i treba da tražiš dalje. Prošli smo kroz te uzroke u tekstu o tome zašto je WordPress sajt spor i kad cache nije glavni krivac.
Šta HPOS menja
HPOS je skraćenica od High Performance Order Storage. Ideja je prosta: porudžbine dobijaju svoje tabele, napravljene baš za njih, sa kolonama i indeksima koji imaju smisla.
Umesto da se sve gura u wp_posts i wp_postmeta, podaci idu u četiri namenske tabele:
wp_wc_orders, osnovni podaci o porudžbini: status, iznos, valuta, kupac, datumwp_wc_order_addresses, adrese za naplatu i dostavuwp_wc_order_operational_data, tehnički podaci kao što su verzija, način plaćanja i podaci o kuponimawp_wc_orders_meta, sve što ostane i što dodaju plugini
Razlika je u tome što customer_id, status i date_created sada nisu tekstualne vrednosti zakopane u meta tabeli, nego prave kolone sa indeksom. Baza više ne mora da pretražuje milione redova da bi našla porudžbine jednog kupca. Ona odmah skoči na pravo mesto.
Koliko to stvarno donosi
Ovo nisu marketinške priče, WooCommerce je objavio merenja. Nekoliko brojeva iz njihovog benchmarka:
- kreiranje 1.000 porudžbina traje 15,18 sekundi sa HPOS-om, prema 78,12 sekundi na starom sistemu, dakle oko pet puta brže
- upit koji vraća sve porudžbine jednog kupca je do 40 puta brži, jer sada postoji indeks nad kolonom
customer_id - sortiranje i filtriranje spiska porudžbina je do pet puta brže
- sam spisak porudžbina se učitava oko dvaput brže
Uz to je u novijim verzijama sređeno i brojanje nesinhronizovanih porudžbina, koje se sada radi samo dok sinhronizacija zaista traje. Na velikim bazama je to upit koji je padao sa oko 400 milisekundi na 1,5 milisekundu.
Još jedna stvar koju treba da znaš. HPOS je podrazumevano uključen za sve nove instalacije od verzije 8.2, a od serije 10.x je standard za novootvorene prodavnice. Stari način čuvanja porudžbina još uvek nije ukinut i nema objavljenog roka za gašenje, ali smer je jasan: nove funkcije i optimizacije se pišu za HPOS.
Kako da proveriš da li si već na HPOS-u
Idi na WooCommerce, pa Settings, pa Advanced, pa Features. Tamo piše da li je High Performance Order Storage uključen i da li je uključena kompatibilnost sa starim tabelama.
Preko WP-CLI je brže:
wp option get woocommerce_custom_orders_table_enabled
Ako vrati yes, na HPOS-u si. Ako vrati no ili ništa, porudžbine ti i dalje žive u wp_posts.
Prelazak, korak po korak
Ovo nije dugme koje se stisne u produkciji u petak popodne. Redosled je bitan.
1. Napravi bekap baze. Ne bekap sajta, bekap baze, i proveri da si u stanju da ga vratiš. Migracija porudžbina je operacija koja se ne poništava jednim klikom.
2. Proveri koji plugini nisu spremni. WooCommerce sam neće dozvoliti da uključiš HPOS ako ima nekompatibilnih dodataka. Spisak vidiš tako što otvoriš stranicu sa pluginovima i dodaš parametar ?plugin_status=incompatible_with_feature&feature_id=custom_order_tables. Tu se najčešće nađu stariji plugini za fakturisanje, dostavu, izvoz porudžbina i domaći platni gateway-i.
3. Uključi kompatibilni režim. To je opcija koja upisuje porudžbine u oba sistema istovremeno. Neko vreme trošiš duplo na upis, ali imaš put nazad: ako nešto pukne, vraćaš prekidač i podaci su i dalje na starom mestu.
4. Pokreni sinhronizaciju. Kroz interfejs se to zna zaglaviti na velikim bazama, jer ide preko Action Scheduler-a. Preko WP-CLI je pouzdanije:
wp wc cot sync
wp wc cot verify_cot_data
Prva komanda prebacuje porudžbine, druga proverava da su podaci u oba sistema isti. Na deset hiljada porudžbina računaj na desetak minuta, na sto hiljada može i nekoliko sati.
5. Prebaci autoritet na HPOS tek kad verifikacija prođe bez razlika. Kompatibilni režim ostavi uključen još dve nedelje. Ako se ništa ne polomi, isključi ga i oslobodi duplu upisnu operaciju.
6. Testiraj ceo tok kupovine. Nova porudžbina, plaćanje, promena statusa, povraćaj, mejl kupcu, izvoz za knjigovođu. Baš tim redom, na pravoj porudžbini.
Ako držiš tuđe prodavnice, ovo je posao koji se radi na staging kopiji, ne uživo. Kod nas svaki paket ima staging okruženje baš zbog ovakvih stvari, a koliko resursa dobijaš po paketu možeš da vidiš u specifikacijama svih paketa.
Šta HPOS neće rešiti
Ovde ljudi najčešće pogreše u očekivanjima. HPOS ubrzava rad sa porudžbinama. On ne ubrzava sve ostalo.
Korpa i blagajna se i dalje ne mogu keširati, jer je svaki prikaz drugačiji za svakog kupca. Svaki taj zahtev ide u PHP, na server, u bazu. Ako imaš dva PHP workera, treći kupac koji je u istoj sekundi na blagajni čeka u redu. Nikakva promena strukture baze to ne menja, jer je to pitanje resursa hostinga, a ne WooCommerce koda.
Isto važi i za pretragu proizvoda, za AJAX filtere u katalogu i za administratorski deo dok ubacuješ proizvode. To su sve nekeširani zahtevi koji jedu isti PHP resurs.
Zato prodavnica sa ozbiljnim prometom traži okruženje koje računa na to. Naš WooCommerce hosting je podešen tako da nekeširani zahtevi imaju gde da se izvrše, sa dovoljno PHP workera i Redis object cache-om koji rasterećuje bazu. Ako držiš običan WordPress sajt bez prodavnice, dovoljan ti je WordPress hosting, tamo se ova priča ne postavlja.
Ako hoćeš da ideš dalje od baze, prošli smo kroz ostatak posla u čeklisti za ubrzavanje WooCommerce prodavnice.
Ukratko
Ako ti admin postaje spor, a broj porudžbina raste, ne troši vreme na još jedan cache plugin. Proveri da li si na HPOS-u. Ako nisi, uradi bekap, proveri plugine, uključi kompatibilni režim, sinhronizuj preko WP-CLI i tek onda prebaci autoritet.
Za prodavnicu sa pet hiljada porudžbina ovo je posao od jednog popodneva koji ti vrati admin u stanje u kome je bio prvog dana. A za prodavnicu koja tek raste, najbolje vreme da to uradiš je sada, dok su tabele još male i dok migracija traje deset minuta umesto tri sata.