Inhoud
- Wat je nodig hebt
- De trage queries vinden
- Migreren naar HPOS (High-Performance Order Storage)
- De tabellen opschonen die meegroeien naast orders
- Het resultaat controleren
- Terugkerend onderhoud inrichten
- Wanneer je hulp moet inschakelen
Wat je nodig hebt
- Een WooCommerce-shop op WooCommerce 8.2 of nieuwer (de versie die HPOS als stabiel en standaard markeerde voor nieuwe installaties). Oudere versies kun je gewoon eerst updaten.
- SSH- of WP-CLI-toegang tot de server. De meeste stappen gebruiken
wp-commando's. Heb je alleen wp-admin, dan dekt het scherm WooCommerce > Status > Gereedschap een deel van dezelfde acties, maar CLI is sneller en preciezer bij grote tabellen. - Een actuele databasebackup. Elke stap hieronder is omkeerbaar, maar een backup betekent dat je niet op dat woord hoeft te vertrouwen. Op managed hosting: check dat je dagelijkse backup minder dan 24 uur oud is. Op een eigen server:
wp db export backup-$(date +%Y%m%d).sql. - Toegang tot phpMyAdmin, Adminer of directe MySQL/MariaDB CLI voor diagnostische queries.
- Kennis van waarom WooCommerce andere druk op de database legt dan een contentsite. Dat concept-artikel behandelt het "waarom"; dit artikel behandelt het "hoe".
De trage queries vinden
Voordat je iets verandert: achterhalen wat eigenlijk traag is. De verkeerde fix voor de verkeerde bottleneck kost je alleen maar tijd.
Stap 1. Installeer Query Monitor op een staging-kopie (nooit productie voor debugging). Open het admin-orderscherm. Sorteer in het Query Monitor-paneel queries op duur. De top drie queries vertellen je of de kosten in wp_postmeta-joins zitten (legacy order storage), in wp_wc_orders-lookups (HPOS), of ergens heel anders.
Stap 2. Check welke orderopslag actief is. Ga in wp-admin naar WooCommerce > Instellingen > Geavanceerd > Functies. Staat er "WordPress posts storage" bij "Order data storage", dan draait de shop op legacy en is HPOS-migratie de grootste enkelvoudige verbetering. Staat er "High-Performance Order Storage", dan is HPOS al actief en zit de bottleneck ergens anders: verweesde data, Action Scheduler-bloat of autoload-druk in wp_options.
Stap 3. Meet de omvang van de tabellen die typisch opzwellen. Draai dit in je databaseclient:
SELECT
table_name,
ROUND(data_length / 1024 / 1024, 1) AS data_mb,
ROUND(index_length / 1024 / 1024, 1) AS index_mb,
table_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name IN (
'wp_postmeta', 'wp_posts',
'wp_wc_orders', 'wp_wc_orders_meta',
'wp_actionscheduler_actions', 'wp_actionscheduler_logs',
'wp_woocommerce_sessions', 'wp_options'
)
ORDER BY data_length DESC;
Op een shop met 100.000+ bestellingen die nooit is opgeschoond kan wp_actionscheduler_logs alleen al tientallen gigabytes bereiken. Die tabel heeft niks met orderopslag te maken, maar alles met hoe traag de admin aanvoelt.
Migreren naar HPOS (High-Performance Order Storage)
Draait de shop nog op legacy post-based orderopslag, dan is dit veruit de grootste performancewinst die er te halen valt. WooCommerce's eigen benchmarks op een testshop met 400.000 orders laten het verschil zien:
| Operatie | Legacy (wp_posts) | HPOS | Verbetering |
|---|---|---|---|
| 1.000 orders aanmaken | 78,1 s | 15,2 s | ~5x sneller |
| 10 checkouts | 1,51 s | 0,99 s | ~1,5x sneller |
| Zoeken op metadata | 0,639 s | 0,053 s | ~10x sneller |
| Filteren op klant-ID | 0,599 s | 0,016 s | ~40x sneller |
De reden is structureel. Legacy storage schrijft zo'n 40 rijen per order (een naar wp_posts, ~39 naar wp_postmeta). HPOS schrijft maximaal 5 rijen over vier eigen tabellen met indexen die precies passen bij de queries die WooCommerce draait.
De migratiestappen
Stap 1. Draai eerst de compatibiliteitscheck. Ga naar WooCommerce > Instellingen > Geavanceerd > Functies en bekijk de compatibiliteitsstatus. WooCommerce markeert extensies die nog geen HPOS-ondersteuning hebben gedeclareerd. Een incompatibele extensie blokkeert de migratie niet per se, maar het betekent wel dat je op staging moet testen voordat je productie aanraakt.
Stap 2. Schakel HPOS in met synchronisatie aan. Dit is het veilige pad: zowel de oude als de nieuwe tabellen blijven in sync, dus terugdraaien is een instellingswijziging, geen datarecovery.
wp wc hpos enable --with-sync
Of in wp-admin: zet "Order data storage" op High-Performance Order Storage en houd "Compatibiliteitsmodus inschakelen" aangevinkt. Vanaf dit moment schrijven nieuwe orders naar HPOS-tabellen en worden ze teruggesynchroniseerd naar wp_posts. Bestaande orders moeten nog gemigreerd worden.
Stap 3. Synchroniseer bestaande orders. Op een shop met minder dan 100.000 orders is de ingebouwde achtergrondsynchronisatie meestal binnen een paar uur klaar. Bij grotere shops is de CLI betrouwbaarder:
wp wc hpos sync --batch-size=500
WooCommerce's migratiegids voor grote shops beschrijft een shop met 9 miljoen orders waar de CLI-sync ongeveer een week duurde. Die gids raadt een drietrapsaanpak aan: houd sync-on-read actief voor de eerste ~6 uur, zet het dan uit, en zet na ~1 week ook sync-on-write uit zodra je de data-integriteit hebt bevestigd.
Stap 4. Verifieer de data-integriteit na afloop van de sync:
wp wc hpos verify_cot_data --verbose
Dit commando vergelijkt orders over beide backends en rapporteert elke mismatch. Nul mismatches betekent dat de migratie schoon is.
Stap 5. Zodra je zeker bent, schakel je de compatibiliteitsmodus uit om de overhead van dubbel schrijven te stoppen:
wp wc hpos compatibility-mode disable
Gaat er toch iets mis, dan is het officiële terugdraaipad expliciet: synchronisatie weer aanzetten, wachten tot de tabellen gelijk lopen, en dan terugswitchen naar posts storage. Beide richtingen zijn hot migrations zonder downtime.
Let op voor april 2026 en later: WooCommerce 10.7, gepland op 14 april 2026, schakelt sync-on-read standaard uit. Dit raakt shops die custom code hebben die orders rechtstreeks naar wp_postmeta schrijft (buiten de WooCommerce CRUD-laag om). Heb je maatwerk-integraties die wp_update_post() of update_post_meta() gebruiken voor orderdata, test ze dan voordat je naar 10.7 upgradet.
De tabellen opschonen die meegroeien naast orders
HPOS-migratie fixt het query-pad voor orders. Onderstaande stappen pakken de tabellen aan die op elke actieve WooCommerce-shop stilletjes opzwellen, ongeacht welke orderopslag actief is.
Action Scheduler-logs
De tabel wp_actionscheduler_logs registreert een log-entry voor elke scheduled action die WooCommerce en extensies draaien. De standaard retentie is 30 dagen, en de standaard opruimbatch is 20 rijen per keer. Op een shop die honderden orders per dag verwerkt, kan het opruimen het niet bijbenen en groeit de tabel ongebreideld. GitHub-issue #26818 documenteert shops waar deze tabel tot 55 GB+ groeide.
Ruim de achterstand op:
# Verwijder afgeronde acties ouder dan 7 dagen (pas de drempel aan naar wens)
wp action-scheduler clean --before="7 days ago" --status=complete
Verhoog daarna de opruimbatch zodat die voortaan bijblijft. Voeg dit toe aan functions.php van je thema of een site-specifieke plugin:
// Verhoog Action Scheduler cleanup van 20 naar 500 per batch
add_filter('action_scheduler_cleanup_batch_size', function () {
return 500;
});
Verlopen WooCommerce-sessies
De tabel wp_woocommerce_sessions slaat winkelwagen-sessiedata op voor elke bezoeker die iets aan de cart toevoegt. Verlopen sessies van afgebroken bestellingen hopen zich op en worden niet op elke shop automatisch opgeruimd. Verwijder ze:
DELETE FROM wp_woocommerce_sessions
WHERE session_expiry < UNIX_TIMESTAMP();
Op een shop met veel verkeer kan dit honderden megabytes vrijmaken.
Verweesde postmeta
Als de shop jarenlang op legacy storage draaide voordat je migreerde naar HPOS, bevat wp_postmeta waarschijnlijk verweesde rijen: meta-entries waarvan de bovenliggende post niet meer bestaat, revisie-meta die nergens meer voor dient, en overgebleven data van verwijderde extensies. De veilige diagnostische query:
SELECT COUNT(*)
FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;
Is het aantal substantieel (duizenden of meer), verwijder de wezen dan:
DELETE pm
FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;
Autoload-data in wp_options
WooCommerce-extensies zijn een veelvoorkomende bron van autoload-bloat in wp_options. Sessiedata, grote productattribuut-arrays en extensie-instellingen stapelen zich op. Het autoload-artikel beschrijft de volledige diagnostiek en opruim-workflow. De korte versie: als je autoloaded data de 800 KB overschrijdt (de WordPress 6.6 Site Health-drempel), is dat onafhankelijk van orderopslag de moeite waard om aan te pakken.
Postrevisies
WordPress slaat revisies op voor elke bewaarde wijziging. Order-edits op legacy storage maakten ook postrevisies aan. Beperk ze in wp-config.php:
define('WP_POST_REVISIONS', 5);
Ruim bestaande overtollige revisies op:
wp post delete $(wp post list --post_type=revision --format=ids) --force
Het resultaat controleren
Draai na alle stappen de tabelgrootte-query uit de diagnostische stap opnieuw. Vergelijk de data_mb-waarden voor en na. Op een shop die op legacy storage draaide met 100.000+ bestellingen en nooit was opgeschoond, heb ik de totale databaseomvang 40 tot 60 procent zien krimpen.
Open daarna het admin-orderscherm. Filter, zoek, sorteer op datum. Op een shop die van legacy naar HPOS is gemigreerd is het verschil meestal meteen duidelijk: een scherm dat er 8 tot 12 seconden over deed, laadt in minder dan 2.
Terugkerend onderhoud inrichten
Het opruimen hierboven is geen eenmalige actie. Deze tabellen groeien gewoon terug.
- Action Scheduler: het
action_scheduler_cleanup_batch_size-filter uit de eerdere stap houdt de tabel onder controle. Check de tabelgrootte elk kwartaal. - Verlopen sessies: stel een gepland WP-CLI-commando of een servercron in die maandelijks de sessie-cleanup-SQL draait.
- Autoload-audit: draai de vier-waarden autoload-meetquery elk kwartaal. Vijf minuten checken voorkomt maanden opgebouwde overhead.
- Tabeloptimalisatie: draai
wp db optimizemaandelijks om schijfruimte terug te claimen van verwijderde rijen. InnoDB geeft ruimte niet automatisch terug aan het bestandssysteem na grote deletes.
Wanneer je hulp moet inschakelen
Als het admin-orderscherm na HPOS-migratie en een volledige opruimronde nog steeds traag is, liggen de overgebleven oorzaken doorgaans buiten wat je zelf kunt oplossen:
- N+1-queries van extensies. Een extensie die per orderrij op het admin-lijstscherm een databasequery draait, levert een lineaire vertraging op die geen enkele opruimactie fixt. Query Monitor op staging laat de schuldige zien. De oplossing is meestal een pluginvervanging of een supportticket bij de extensie-ontwikkelaar.
- InnoDB buffer pool te klein voor de working set. Heeft de databaseserver 1 GB RAM en zijn de gezamenlijke WooCommerce-tabellen 4 GB, dan leest MySQL constant van schijf.
innodb_buffer_pool_sizemoet groot genoeg zijn om de working set vast te houden. Op managed hosting is dit een supportticket. Op een eigen server: zet het op 50 tot 70 procent van het beschikbare RAM. De MySQL 8.0 optimalisatiehandleiding behandelt de tuning. - Read replicas voor rapportages. Draait de shop zware WooCommerce Analytics-queries tegelijk met orderverwerking, dan concurreren die rapportqueries met checkout-queries om databaseresources. Rapportages naar een read replica offloaden scheidt de workloads volledig. Dit is een infrastructuurwijziging, geen WordPress-wijziging.
Wanneer je hulp inschakelt, heb dan dit paraat: de output van de tabelgrootte-query, de actieve orderopslag-backend (HPOS of legacy), je WooCommerce- en PHP-versies, of er een object cache actief is (Redis of Memcached), en de drie traagste queries uit Query Monitor op het betreffende scherm. Dat is genoeg om mee te triagen zonder een tweede ronde.