- A katalógusnövekedés üzemeltetési projekt, a terhelés az adminban és a háttérfolyamatokban jelenik meg először, nem a vásárlói oldalon.
- Mielőtt bármihez hozzányúlsz, mérd meg a lassú lekérdezéseket, a háttérsor hosszát és az egyes feladatok futásidejét.
- A beavatkozás javasolt sorrendje az ütemezés, utána a kötegelés, végül az indexelés és csak ezek után az architektúra cseréje.
- Egy monolit éjszakai feladatot érdemes független, egyenként újraindítható lépésekre bontani, saját zárolással és naplóval.
- A feedben és az oldalon lévő elavult ár vagy készlet a hirdetéseknek és az AI-alapú válaszoknak is pontatlan adatot ad.
Egy webshop ezer termékkel és ugyanez a webshop tizenötezer termékkel két különböző rendszer, akkor is, ha ugyanaz a sablon, ugyanazok a bővítmények és ugyanaz a tárhely fut alatta. A vásárló sokszor semmit nem vesz észre a különbségből, mert a termékoldalakat és a kategóriákat gyorsítótár védi. Az admin, a háttérfolyamatok és a külső szinkronok viszont gyorsítótár nélkül, közvetlenül az adatbázison dolgoznak, ezért a terhelés ott jelentkezik először. Ez a cikk végigveszi, mi romlik el, hogyan méred, és milyen sorrendben érdemes beavatkozni.

A szövegben háromféle jelölést használunk. A Hivatalosan igazolt rész a platformok és szabványok dokumentációján alapul. A Saját tapasztalat az üzemeltetési munkánk során többször látott mintázat, amelyet nem mértünk tudományos igénnyel. A Szakmai feltételezés pedig logikus következtetés, amelyet a saját rendszereden érdemes ellenőrizni.
Miért üzemeltetési projekt a katalógusnövekedés, és miért nem adatfeltöltés?
Azért, mert a termékszám növekedésével a folyamatok futásideje és erőforrásigénye nő, nem csak a tárolt adat mennyisége. Ha a beszállítói importot, a tömeges árazást és a feedgenerálást ugyanúgy hagyod, ahogy ötezer terméknél működött, akkor ugyanazok a lépések egyre tovább futnak, egymásra csúsznak, és végül időtúllépéssel leállnak.
Saját tapasztalat: a webshopok többségénél a bővülést adatfeltöltési feladatként kezelik. Valaki feltölti a CSV-t, az import lefut, és a csapat kipipálja a feladatot. A gondok hetekkel később jönnek elő, amikor az éjszakai árszinkron már reggel kilenckor is fut, és lassítja az ügyfélszolgálat adminmunkáját. Ezért javasoljuk, hogy a katalógusbővítésnek legyen gazdája, mérési alapvonala és üzemeltetési terve, ugyanúgy, mint egy szerverköltöztetésnek.
Mi romlik el elsőként, ha tízezer fölé nő a termékszám?
Jellemzően négy terület kezd akadozni. Lelassul az adminkeresés, időtúllépéssel leáll a tömeges szerkesztés, elhúzódik az árszinkron, és akadozik a feedgenerálás. Ezek nem egyszerre jelentkeznek, de közös a gyökerük, mert mind sok sort olvasnak és írnak egyetlen kérésen vagy egyetlen futáson belül.
Lassuló adminkeresés
Hivatalosan igazolt: a MySQL dokumentációja szerint a LIKE '%szó%' típusú, elején helyettesítő karakterrel induló keresés nem tudja használni a szokásos B-fa indexet, ezért a teljes táblát vagy nagy részét végig kell olvasnia. WordPress-alapú áruházaknál az adminkeresés hagyományosan ilyen mintázattal dolgozik a címben, a tartalomban és sokszor a metaadatokban is. A WooCommerce a 3.6-os verzió óta külön keresőtáblát (wc_product_meta_lookup) tart fenn többek között a cikkszámhoz, az árhoz és a készlethez, hogy ezek a lekérdezések ne a teljes metatáblán fussanak.
Saját tapasztalat: a lassulást gyakran egy bővítmény okozza, amely a keresést kiterjeszti az összes egyedi mezőre. Ötezer terméknél ez még elviselhető, tizenötezer terméknél és több százezer metasornál már másodpercekben mérhető.
Időtúllépéses tömeges szerkesztés
A tömeges szerkesztés egyetlen webes kérésben próbál több száz terméket módosítani. Minden mentés újraszámolja a keresőtáblát, törli a gyorsítótárat, és sokszor bővítményes műveleteket is kivált. Hivatalosan igazolt: a PHP max_execution_time beállítása és a webszerver vagy proxy időkorlátja megszakítja a túl hosszú kérést, és ilyenkor a módosítás egy része megtörténik, másik része nem.
Elhúzódó árszinkron
Az árszinkron (beszállítói vagy ERP-alapú) sokszor termékenként egy API-hívással és egy mentéssel dolgozik. Szakmai feltételezés: ha egy termék frissítése a teljes mentési láncon keresztül átlagosan néhány tized másodpercig tart, tízezer terméknél ez önmagában órákat jelent, és ehhez jön a külső API válaszideje és sebességkorlátja.
Akadozó feedgenerálás
A termékfeed (például a Google Merchant Center vagy egy árösszehasonlító számára) a teljes katalógust végigolvassa. Ha a generálás webes kérésben vagy a WordPress beépített ütemezőjén fut, könnyen félbeszakad, és a hirdetési rendszer egy félkész vagy régi fájlt tölt le.
Hogyan mérd, hol a szűk keresztmetszet?
Az adatbázis lassú lekérdezéseit, a háttérsor hosszát és az egyes feladatok futásidejét mérd, legalább egy hétig, mielőtt bármit átállítanál. Mérés nélkül könnyen a tárhelyet bővíted, miközben a gondot egyetlen rosszul megírt lekérdezés okozza.
- Lassú lekérdezések naplója. Hivatalosan igazolt: a MySQL és a MariaDB is támogatja a
slow_query_logés along_query_timebeállítást. Egy másodperces küszöbbel indulj, és nézd meg, mely lekérdezések ismétlődnek. - EXPLAIN a gyanús lekérdezésekre. Az
EXPLAINmegmutatja, használ-e indexet a lekérdezés, és hány sort vizsgál meg. - Háttérsor állapota. Hivatalosan igazolt: a WooCommerce a háttérfeladatokhoz az Action Scheduler könyvtárat használja, amelynek az adminban van állapotoldala (Eszközök, Ütemezett műveletek). Itt látod a függő, a sikertelen és a késésben lévő feladatok számát.
- Feladatonkénti futásidő. Minden saját szkript írja naplóba a kezdés és a befejezés idejét, valamint a feldolgozott tételek számát. Így látod, ha a futásidő a termékszámnál gyorsabban nő.
- Admin válaszidő. Mérd meg a terméklista és a keresés betöltési idejét, például a böngésző fejlesztői eszközével vagy egy alkalmazásteljesítmény-figyelő eszközzel.
Egy egyszerű ellenőrző lekérdezés, amellyel megnézed, mennyi metaadat tartozik a termékekhez:
SELECT COUNT(*) FROM wp_postmeta pm JOIN wp_posts p ON p.ID = pm.post_id WHERE p.post_type IN ('product','product_variation');
Saját tapasztalat: ha ez a szám a termékszám ötvenszerese fölé megy, szinte mindig találunk elárvult vagy bővítmény által hátrahagyott metaadatot, amelynek a takarítása önmagában érezhetően javíthatja az admin sebességét.
Milyen sorrendben érdemes beavatkozni?
A javasolt sorrend az ütemezés, a kötegelés, az indexelés, és csak ezek után a nagyobb architekturális változtatás. Az első három olcsóbb, visszafordítható, és jó eséllyel a gondok nagy részét megoldja. A sorrend saját tapasztalaton alapul, nem szabvány.
- Ütemezés. Válaszd szét az időben ütköző feladatokat. Hivatalosan igazolt: a WordPress beépített ütemezője (WP-Cron) oldalletöltéskor indul, ezért kis forgalomnál késik, nagy forgalomnál pedig felesleges terhelést okoz. A WordPress dokumentációja szerint a
DISABLE_WP_CRONkonstanssal kikapcsolható, és helyette rendszerszintű cron hívhatja meg rendszeres időközönként. - Kötegelés. Egy futás ne tízezer terméket dolgozzon fel, hanem például ötszázas csomagokat, és minden csomag után rögzítse, hol tart. Ha egy köteg elhasal, csak azt kell újrafuttatni. Az Action Scheduler a kötegméretet és a futási időablakot szűrőkkel engedi állítani.
- Indexelés. A lassú lekérdezések naplója alapján célzottan adj indexet, vagy használd a platform saját keresőtábláit. Ha az adminkeresés továbbra is lassú, egy külső keresőmotor (például Elasticsearch vagy OpenSearch) leveheti a terhet az adatbázisról.
- Változásalapú feldolgozás. Az árszinkron csak azt a terméket mentse, amelynek ténylegesen változott az ára vagy a készlete. Szakmai feltételezés: egy átlagos napon a katalógusnak csak kis része változik, így ez a lépés nagyságrendekkel csökkentheti az írások számát.
- Architektúra. Ha az előzőek után is szűk a keresztmetszet, jöhet az erőforrásbővítés, külön adatbázisszerver, objektum-gyorsítótár (például Redis) vagy a WooCommerce nagy teljesítményű rendeléstárolása (HPOS), amely a rendeléseket saját táblákba költözteti.
Shopify-alapú áruháznál a kép más, mert az adatbázist a platform kezeli. Hivatalosan igazolt: a Shopify GraphQL Admin API sebességkorlátot alkalmaz, és nagy adatmennyiség lekérdezéséhez külön tömeges műveleti (bulk operation) mechanizmust kínál. Itt a kötegelés és a változásalapú szinkron szerepe még nagyobb.
Hogyan néz ki egy éjszakai folyamat szétbontása a gyakorlatban?
A monolit éjszakai szkriptet független, egyenként újraindítható lépésekre bontod, mindegyiknek saját időpontja, zárolása és naplója van. Az alábbi példa általános minta, nem egy konkrét áruház beállítása.
A kiinduló állapot egy hajnali egykor induló szkript, amely sorban letölti a beszállítói árlistát, frissíti az összes termék árát és készletét, újragenerálja a feedet, majd üríti a gyorsítótárat. Ha a második lépés elakad, a feed sem készül el, és reggel a hirdetések régi árral futnak.
A szétbontott változat négy lépésből áll:
- Letöltés és ellenőrzés (01:00). Letölti a beszállítói fájlt, ellenőrzi a sorok számát és a formátumot, és csak akkor engedi tovább, ha az eltérés az előző naphoz képest egy előre megadott határon belül van.
- Változások kigyűjtése (01:20). Összeveti az új árakat és készleteket az adatbázissal, és egy átmeneti táblába írja csak a változott tételeket.
- Kötegelt frissítés (01:40-től). Ötszázas kötegekben menti a változásokat, minden köteg után naplóz, és rögzíti az utolsó feldolgozott azonosítót.
- Feedgenerálás (04:00). Külön folyamatként, fájlba írja a feedet, és csak a kész fájlt nevezi át a végleges nevére, így a hirdetési rendszer soha nem tölt le félkész állományt.
A rendszerszintű cron bejegyzés valahogy így nézhet ki:
*/5 * * * * cd /var/www/shop && wp cron event run --due-now --quiet0 1 * * * flock -n /tmp/letoltes.lock php /opt/sync/letoltes.php20 1 * * * flock -n /tmp/valtozas.lock php /opt/sync/valtozas.php40 1 * * * flock -n /tmp/frissites.lock php /opt/sync/frissites.php --koteg=5000 4 * * * flock -n /tmp/feed.lock php /opt/sync/feed.php --kimenet=/var/feed/tmp.xml
A flock -n megakadályozza, hogy egy lépés kétszer fusson egymás mellett, ha az előző még nem végzett. Saját tapasztalat: az egymásra csúszó, párhuzamosan futó példányok okozzák a legtöbb rejtélyes adatbázis-zárolást, és ezt egyetlen sor rendezi.
Hivatalosan igazolt: a Google Merchant Center támogatja a kiegészítő feedet és az API-alapú frissítést, így az ár és a készlet a teljes fő feed újragenerálása nélkül is frissülhet. A Google a Content API for Shopping helyett az új Merchant API felé tereli a fejlesztőket, ezért új integrációnál érdemes már ezt választani.
Mit ellenőrizz a növekedés előtti felkészülésnél?
A bővítés előtt legyen alapvonalad, legyenek szétválasztva a feladatok, és legyen visszaút. Az alábbi lista a saját üzemeltetési gyakorlatunkból áll össze.
- Megvan a jelenlegi futásidő minden háttérfeladatra (import, árszinkron, feed, mentés).
- Be van kapcsolva a lassú lekérdezések naplója, és van egy hetes mintád.
- A WP-Cron helyett rendszerszintű cron hívja az ütemezőt.
- Egyik nagy feladat sem fut webes kérésben, mind parancssorból vagy háttérsorból indul.
- Minden tömeges művelet kötegelt, és újraindítható onnan, ahol megállt.
- Az árszinkron csak a változott tételeket írja.
- A feed átmeneti fájlba készül, és csak a kész fájl kerül élesbe.
- Ki van takarítva az elárvult metaadat és a régi termékváltozat.
- Az adminkeresés nem fut végig minden egyedi mezőn.
- Van objektum-gyorsítótár, és mérted a találati arányát.
- A mentések nem ütköznek az éjszakai szinkronnal.
- Van riasztás, ha egy feladat nem fut le vagy a szokásosnál kétszer tovább tart.
- Tesztkörnyezetben kipróbáltad a várható termékszámot, nem a mostanit.
Mi köze ennek a keresőkhöz és az AI-alapú válaszokhoz?
Ha a háttérfolyamatok késnek, az oldalon, a strukturált adatban és a feedben eltérő ár vagy készlet jelenhet meg, ami a hirdetéseknek és a válaszmotoroknak is pontatlan adatot ad. Hivatalosan igazolt: a Google Merchant Center irányelvei szerint a feedben szereplő árnak és elérhetőségnek egyeznie kell a céloldalon láthatóval, eltérés esetén a termék elutasítható. A Schema.org Product és Offer típusa ugyanezeket az adatokat írja le az oldalon.
Szakmai feltételezés: az AI-alapú keresők és asszisztensek egyre gyakrabban idéznek termékadatot. Ha egy elavult árat vesznek át, azt a vásárló a te hibádnak látja. A stabil, időben lefutó háttérfolyamat tehát a láthatóság egyik alapfeltétele, bár önmagában semmilyen helyezést vagy említést nem garantál.
Források és további olvasnivalók
- MySQL Reference Manual (indexek, EXPLAIN, slow query log)
- WordPress Developer Resources (WP-Cron, DISABLE_WP_CRON)
- WooCommerce Developer Documentation (Action Scheduler, HPOS, termék keresőtáblák)
- Shopify Developer Documentation (GraphQL Admin API sebességkorlát, bulk operations)
- Google Merchant Center súgó és Merchant API dokumentáció
- Google Search Central (termék strukturált adatok)
- Schema.org (Product, Offer)
Gyakori kérdések
Hány terméknél kezd lassulni egy webshop adminja?
Nincs egyetlen határ, mert a termékváltozatok, a metaadatok és a bővítmények száma legalább annyit számít, mint a termékszám. Saját tapasztalatunk szerint a tízezres nagyságrend körül szokott először érezhetővé válni, de mérni kell, nem becsülni.
Elég, ha nagyobb tárhelyre költözöm?
Ritkán. Ha egy lekérdezés index nélkül olvassa végig a táblát, vagy egy feladat webes kérésben fut, a több erőforrás csak késlelteti a gondot. Előbb mérj, ütemezz és kötegelj, a bővítés az utolsó lépés legyen.
Miért rossz, ha a feed webes kérésben generálódik?
Mert a PHP és a webszerver időkorlátja megszakíthatja, és a hirdetési rendszer félkész vagy régi fájlt tölthet le. Parancssorból, átmeneti fájlba érdemes generálni, és csak a kész állományt élesíteni.
Mi az a kötegelés, és miért segít?
A nagy feladatot kisebb, például ötszáz tételes csomagokra bontod, és minden csomag után rögzíted az állapotot. Így egy hiba csak egy csomagot érint, a futás folytatható, és egyik kérés sem fut túl sokáig.
Kell külső keresőmotor az adminkereséshez?
Nem mindig. Sokszor elég a felesleges mezőkre kiterjesztett keresés kikapcsolása és a platform saját keresőtábláinak használata. Ha ezek után is lassú, egy külső keresőmotor leveheti a terhet az adatbázisról.
Források és további olvasnivalók
Ezen az oldalon a hivatalosan igazolt információt elsődleges forrásokból építjük fel; a saját tapasztalatot és a szakmai becslést mindig külön jelöljük a szövegben.