Magento 2 Partiële Herindexering

Magento 2 treft veel maatregelen om de snelheid van de webshop te verhogen. Het heeft meer dan 30 index-tabellen om de shopping-ervaring voor de gebruiker aangenaam te maken, en daarnaast nog een flat product table en een flat category table per store view, als flat tables ingeschakeld zijn.

English translation of this article.

Als database entiteiten als producten, categorieën en klanten aangepast worden, moeten deze indexen worden bijgewerkt. Magento heeft twee manieren om dit te doen, genaamd “Indexeren bij opslaan” (“Update on Save”) en “Volgens schema bijwerken” (“Update by Schedule”).

Ik zal de term “entiteiten” hier gebruiken voor zowel producten, categorieën als klanten.

Indexeren bij opslaan is het makkelijkst uit te leggen. Steeds als een entiteit wordt toegevoegd, gewijzigd, of verwijderd in de backend of via een REST request, worden alle noodzakelijke indexen bijgewerkt om deze wijziging op te vangen. Een groot aantal extra SQL queries worden uitgevoerd in hetzelfde request dat de entiteit toevoegt, bijwerkt, of verwijdert. De index wordt niet volledig opgebouwd, het wordt alleen een beetje aangepast. Specifieke onderdelen van caches worden direct geleegd om ervoor te zorgen dat de wijziging direct zichtbaar is op de webshop.

Volgens schema bijwerken past de indexen niet aan binnen het request. Het is zelfs zo dat Magento alleen die queries uitvoert die nodig zijn om de entiteit te wijzigen, en verder niks. Toch wordt de index bijgewerkt en specieke cache-onderdelen efficiënt geleegd binnen enkele minuten.

In de rest van dit blog artikel zal ik uitleggen hoe deze Volgens-schema-bijwerken-magie werkt.

Hoe werkt het?

In het kort, Magento 2 maakt triggers aan voor elke “Volgens schema bijwerken” index. Deze triggers vuren naar aanleiding van iedere INSERT, UPDATE en DELETE op elk van de tabellen van de entiteit. Bij het vuren schrijven ze een nieuwe regel met de id van entiteit in een specifieke changelog tabel. Als de cron job loopt vergelijkt het de version_id van zijn mview_state tabel met de version_ids uit de changelog tabel. De index wordt bijgewerkt voor alle entiteiten die als gewijzigd zijn gemarkeerd. Ook worden caches voor specifieke entiteiten geleegd.

Ik zal hier nu in meer detail op in gaan.

Volledige Herindexering en Partiële Herindexering

Sommige processen (zowel uit de core als van extensies) maken expliciet de complete index ongeldig. De gebruiker kan dit zien in de backend:

De geldigheid van alle indexen is opgeslagen in de tabel indexer_state:

Magento’s cronjob “indexer_reindex_all_invalid” bouwt alle ongeldige indexen opnieuw op.

Als de cronjobs niet actief zijn, kun je een CLI commando gebruiken om alle indexen opnieuw op te bouwen, of alleen een specifieke index:

Dit commando herbouwt de indexen van de grond af aan. Voor webshops van enige omvang is dit een behoorlijke operatie. Met duizenden producten, een groot aantal categorieën en veel store views, kan dit al snel een uur duren.

Voor een shop in productie is dit onwenselijk. Gelukkig is het aantal gevallen waarin een volledige index herbouwd moet worden klein. Magento 2 kan de meeste aanpassingen aan entiteiten afhandelen door de index incrementeel bij te werken. Dit proces heet partiële herindexering.

Index Beheer and Materialized Views

De indexen en flat tables zijn binnen Magento 2 bekend als “mviews”.

Een “view”, in database terminologie, is een virtuele tabel die het resultaat weergeeft van een SELECT query. De view is live: het geeft steeds de actuele toestand van de data weer.

Een “materialized view” is een virtuele tabel die het opgeslagen resultaat weergeeft van een SELECT query. De inhoud is niet live, maar moet regelmatig worden bijgewerkt. Een materialized view is veel sneller dan een normale view omdat het eenvoudig uit te lezen is.

MySQL kent geen echte materialized views, maar een normale tabel kan als zodanig dienst doen. Dit is wat Magento doet. Magento’s “indexen” and “flat tables” zijn zulke materialized views.

In de backend kun je selecteren op welke manier Magento de indexen moet bijwerken. Je kunt dit per per index aangeven.

Als voorbeeld dat ik verder uitwerk, stel ik alleen de index “Product Platte Data” (catalog_product_flat) in op “Volgens schema bijwerken” en de rest op “Indexeren bij opslaan”.

Het effect op de database van deze admin actie wordt weergegeven in de tabel mview_state:

Zoals je ziet, is alleen de index “catalog_product_flat” is ingeschakeld. Merk op dat de tabel een kolom version_id heeft. Hier komen we zo op terug.

Triggers

Een database trigger is een event handler die reageert op veranderingen in a database tabel.

Als een index ingesteld wordt op “Volgens schema bijwerken”, maakt Magento 2 er een aantal triggers voor aan. Voor catalog_product_flat alleen al worden 30 triggers aangemaakt. Ik zal er hier slechts 3 tonen:

De 3 triggers die je hier ziet corresponderen allen met veranderingen in de tabel “catalog_product_entity” (zie Table). De events zijn INSERT, UPDATE, en DELETE. Omdat er 10 tabellen bestaan die als bron dienen voor de inhoud van de materialized view catalog_product_flat, zijn er 3 x 10 = 30 triggers nodig om alle gevallen af te dekken.

De event handlers voor de “catalog_product_flat” index schrijven allemaal een enkele record in de changelog tabel “catalog_product_flat_cl”:

Elke index heeft zijn eigen changelog (cl) tabel. De tabel toont alleen de id’s van de entiteiten die “dirty” zijn, en wiens index entry toegevoegd, gewijzigd of verwijderd moet worden.

De Entiteit Wordt Gewijzigd

Als een entiteit wordt gewijzigd, via de backend, via een REST call, of zelfs via een directe SQL query in phpMyAdmin, vuren sommige triggers.

De triggers vuren uitbundig, zodat een enkele wijziging aan een entiteit meerdere regels in de changelog tabel tot gevolg heeft:

De version_id kolom is slechts een auto-increment veld.

De Cronjob Partiële Herindexering

In een doorsnee Magento installatie, runt de cron job ieder minuut. De cron job voert vele taken uit. Een van deze is “indexer_update_all_views”. Deze taak controleert voor iedere index of de version_id uit mview_state overeenkomt met de version_ids uit zijn changelog tabel.

De entity_ids van de changelog records met version_id groter dan de version_id uit mview_state worden verzameld, en de index wordt bijgewerkt voor deze entiteiten.

De cronjob leegt ook alle nodige caches. Dit gebeurt heel precies. Specifieke product-pagina en categorie-pagina caches worden geleegd. Niet de hele full page cache.

Daarna wordt de version_id in mview_state opgehoogd tot de hoogste version_id uit de changelog table.

Ieder uur verwijdert een andere cronjob, “indexer_clean_all_changelogs” alle changelog records met version_id kleiner dan die in mview_state.

Conclusie

Magento 2 stelt je in staat om producten van buiten af en van binnen uit te wijzigen. Ze kunnen niet alleen worden gewijzigd via the user interface (buiten), maar ook via direct database queries (binnen). “Volgens schema bijwerken” werkt de nodige indexen bij voor je.

Als je catalogus-producten wilt bijwerken op een manier die niet mogelijk is via Magento’s admin panel, of die sneller via een directe SQL query met phpMyAdmin of met een script kunnen worden uitgevoerd, dan is dit nog steeds mogelijk, zelfs op een productie webshop. Je hebt natuurlijk wel een goede kennis nodig van Magento’s MySQL tabellen. Maar de partiële herindexeringstechnieken van “Volgens schema bijwerken” zorgen ervoor dat alle noodzakelijke indexen en flat tables bijgewerkt worden, en dat zelfs specifieke caches geleegd worden.

Referenties

Reacties:

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.