Probeer 14 dagen gratis
Skip to content

WooCommerce lookup table nog traag bij grote catalogi

De WooCommerce product attributes lookup table, wc_product_attributes_lookup, haalt de zware term-join uit de catalogusquery. Ze haalt de klik niet van de server. Een AJAX-filter start bij elke filteractie nog steeds PHP, leest die tabel, en telt de opties opnieuw. InstantFilter leest deze tabel niet. Na de eerste pageload filtert de browser op een eigen index, in 1,5 ms tot 5 ms, met 0 SQL.

Wat is de WooCommerce product attributes lookup table?

Sinds WooCommerce 6.3 bouwt WooCommerce een aparte tabel voor filteren op attributen. De aankondiging staat op de WooCommerce Developer Blog van 2 februari 2022: een migratie maakt de tabel, een scheduled action vult hem, en de instelling “Use the product attributes lookup table for catalog filtering” zet hem aan voor de shop. Staat die uit, dan valt het filteren terug op de posts-tabellen, zoals vóór deze tabel.

De tabel heet wp_wc_product_attributes_lookup. WooCommerce beschrijft haar als gedenormaliseerde data voor catalogusfiltering. Het beheer gaat via WP-CLI: wp wc palt kan de tabel aanzetten, uitzetten, inspecteren en opnieuw opbouwen. wp wc palt regenerate vult haar in één run, zonder te wachten op de action scheduler. regenerate_for_product doet dat voor één product en zijn variaties. Dat staat in de CLI-documentatie en in de optimalisatie-aankondiging van 20 juni 2024.

Als je zoekt op woocommerce product attributes lookup table slow of op de naam wc_product_attributes_lookup, zit je in deze laag. De tabel is de officiële WooCommerce-fix voor trage attribuutfilters. Ze is geen bug. Ze is een vooraf berekende relatie tussen product en term, zodat MySQL niet bij elke klik dezelfde taxonomie-join hoeft te verzinnen.

Waarom blijft wc_product_attributes_lookup traag bij tienduizenden producten?

De tabel versnelt het opzoeken van “welke producten hebben term rood”. Ze verwijdert niet de architectuur waarin elke klik de server vraagt. De browser post nog steeds naar admin-ajax.php of naar een REST-route. WordPress start. PHP leest wc_product_attributes_lookup. Daarna telt de filterplugin hoeveel producten er bij elke overgebleven optie horen. Die telling is een tweede query, vaak per facet.

Op een catalogus van 10.000, 20.000 of 50.000 producten wordt de tabel zelf groot. Elke variatie met een attribuut is een rij. Regenereren, via de tool onder WooCommerce → Status → Tools of via wp wc palt regenerate, loopt in batches en kan op een drukke shop lang duren. De Developer Blog van 2024 beschrijft die regeneratie juist omdat de tabel bij grote catalogi onderhoud nodig heeft. Een trage regenerate is een admin-probleem. Een trage klik is een ander probleem: de request bestaat nog.

Direct updaten bij elke productwijziging, de optie die WooCommerce in 6.3 noemt, houdt de tabel gelijk met de catalogus. Het maakt de filterklik niet lokaal. De shopper betaalt nog steeds de PHP-boot en de round-trip. Op hosting waar PHP-workers schaars zijn, vult een sale de wachtrij ook als de SQL zelf korter is dan de oude join op wp_term_relationships.

Hoe verhoudt deze tabel zich tot wp_postmeta?

De vorige generatie van hetzelfde probleem staat in de post over trage filters en wp_postmeta. Globale attributen leven als termen. Lokale attributen en veel prijs- of voorraadvelden zitten in postmeta. Filterplugins die daar per klik op joinen, worden traag zodra de catalogus groeit. De lookup table is WooCommerce’s antwoord op de attribuut-join, niet op postmeta, en niet op de request.

Een shop kan beide tegelijk hebben. Attribuutfilters lezen wc_product_attributes_lookup. Prijs, voorraad of een custom veld leest nog steeds meta. Query Monitor laat dan een snelle lookup zien en daarnaast een trage meta-query in dezelfde admin-ajax.php-call. De tabel “aan” zetten haalt die tweede query niet weg. Je ziet het doordat de klik na het regenereren nog steeds honderden milliseconden tot een paar seconden duurt.

Leest InstantFilter de product attributes lookup table?

Nee. InstantFilter bouwt tijdens het indexeren een eigen index en exporteert een gecomprimeerd codebook. De documentatie van het indexeren beschrijft dat bestand: de browser downloadt het na de server-render, en latere klikken lossen in het geheugen op, zonder de database. De lookup table van WooCommerce kan op de site gewoon aan staan voor andere onderdelen van WooCommerce. De filterklik van InstantFilter gaat er niet doorheen.

Dat onderscheid hoort in de zin te blijven. InstantFilter is geen laag bovenop wc_product_attributes_lookup. Het vervangt de vraag “tel dit archief opnieuw op de server” door een index die al geteld is vóór de shopper klikt. De eerste HTML blijft server-side, zodat de categorie indexeerbaar is. De interactie daarna kost 0 SQL.

Wanneer merk je dat de lookup table het filter niet heeft opgelost?

Drie controles. Eén: WooCommerce → Status → Tools toont dat de lookup table is opgebouwd, en de instelling voor catalogusfiltering staat aan. Twee: het Network-tabblad toont bij een klik nog steeds een request. Drie: Query Monitor of het slow query log noemt wc_product_attributes_lookup in die request, naast eventueel postmeta. Als één en twee allebei waar zijn, heeft de officiële fix de join verplaatst en de architectuur laten staan.

De hub daarachter is de gids over waarom filters traag worden. Deze pagina is het specifiekere scherm: de tabel die WooCommerce zelf heeft toegevoegd, en die bij een grote catalogus toch niet verhindert dat elke klik PHP start. Regenereren is zinvol als de tabel leeg of achterloopt. Het is geen antwoord op een request per klik.

Facet-tellingen blijven de vermenigvuldiger. Eén productquery plus een count per optie is, ook op een nette lookup table, een burst van SQL binnen dezelfde worker. Bij twintig zichtbare kleuren zijn dat twintig counts, tenzij de plugin ze in één query propt. Die query wordt langer naarmate de tabel meer rijen heeft. De shopper wacht op het laatste getal, niet op de eerste productkaart.

Wat verander je als de lookup table aan staat en de klik traag blijft?

Laat de tabel aan voor WooCommerce. Verplaats de filterklik van de server af. Na hydratatie telt InstantFilter de opties in de browser op de producten van het huidige archief. Er gaat dan geen SELECT naar wc_product_attributes_lookup voor die klik. De 800 ms tot 2.500 ms van een AJAX-round-trip vallen weg, omdat de round-trip er niet is. De interactie zit in 1,5 ms tot 5 ms.

Test het naast elkaar op staging. Noteer of de lookup table enabled is, klik een attribuut, en lees de request-tijd. Zet daarna het archief op InstantFilter en klik hetzelfde attribuut. Het slow query log hoort die tweede klik niet te bevatten. Een catalogus van tienduizenden producten maakt het verschil zichtbaar. Het getal is de test, niet de titel van de pagina.

Hoe zie je in Query Monitor dat de lookup table de klik nog doet?

Zet Query Monitor aan op een staging-kloon, open een categorie met veel attributen, en klik één facet aan. In de query-lijst van die request zoek je op wc_product_attributes_lookup. Staat de tabel erin, dan gebruikt de actieve filter de officiële WooCommerce-index. Tel daarna het aantal queries in dezelfde request. Eén SELECT voor de producten plus een reeks COUNT’s voor de overige opties is normaal voor een AJAX-facet, ook als de join zelf netjes op de lookup table staat.

Noteer de duur van de hele request, niet alleen de duur van de snelste SELECT. De shopper wacht op het laatste antwoord. Een lookup van 40 ms gevolgd door tellingen van 600 ms is een trage klik. Vergelijk dat met een tweede klik nadat het archief op InstantFilter staat: die tweede klik hoort geen rij in Query Monitor te hebben, omdat er geen PHP-request is. De tabel mag in de database blijven. Ze hoort alleen niet in de request van de shopper.

Ga verder

De lookup table is één laag. Deze pagina’s zitten ernaast of erboven.

Vragen over de lookup table

Nee. WooCommerce mag de tabel blijven gebruiken. InstantFilter leest haar niet tijdens het filteren. De klik na de eerste load gaat niet door die tabel.
Nee. Regenereren vult de tabel op de achtergrond of via WP-CLI. Een trage filter is de request van de shopper bij elke klik, ook als de tabel al vol is.
Alleen voor het opzoeken van globale productattributen in de catalogus. Prijs, voorraad en lokale attributen kunnen nog in postmeta zitten en nog steeds in dezelfde AJAX-call worden gelezen.
Omdat de actieve filterplugin die tabel per klik bevraagt. De tabel maakt die query korter dan een term-join. Ze maakt de query niet nul.

Klaar om filteren instant te maken?

Download de gratis 14-daagse proefversie van Pro. Geen creditcard nodig — direct testen.