Yapf.net

Uit de loopgraven: "40.000 queries is heel normaal"

Databases zijn er om gebruikt te worden, maar je kunt ook overdrijven. Slecht ontwerp en gebrekkige kennis van zaken is een recept voor totale rampen.

"40.000 queries is heel normaal tijdens het opstarten van een pagina"

Nieuwe website gaat in productie, crasht binnen vier minuten. "Dat zal wel aan de database liggen want dat is PostgreSQL en wij beheren hem niet".

Een kort onderzoek naar de database leert dat voor elke pageview ruim 40.000 queries worden uitgevoerd. "Ja dat is heel normaal tijdens het opstarten, daar moet die database wel tegen kunnen". Hoezo is dat normaal, hoe zou dat moeten werken op een daadwerkelijk populaire website Als er 400 man tegelijk op F5 drukt, moet de database dan maar even 16.000.000 queris gaan afhandelen binnen een halve seconde?

De meeste websites hebben niet eens 40.000 records in de hele database, dus wat is deze code aan het doen? Het blijkft CraftCMS met CraftQL. Wat is het probleem: CraftCMS gebruikt een Entity-Attribute-Value model wat en doet dat niet echt geweldig. Elke entiteit in je datamodel (pagina, blogpost etc) wordt eerst opgeslagen in een 'entity' tabel om de relatie tot andere entities te kuinnen bepalen. Vervolgens worden alle strings, plaatjes etc die bij die blogpost horen weer opgeslagen als entities in diezelfde tabel, met indien nodig een verwijzing naar een andere tabel waar de daadwerkelijke inhoud staat opgeslagen. En omdat alle entities aan elkaar gekoppeld kunnen zijn en de makers van CraftCMS geen SQL spreken wordt er voor elke entity een query gedraaid. Een blogpost met twee textvelden kan dus al drie queries opleveren en als je twee blogposts ophaalt worden er zes queries gedraaid en als je blogpostontwerp tien velden bevat en je hebt 500 posts, dan draai je 11 * 500 = 5500 queries waar in één quer zou volstaan.

Koppel een brak CMS aan GraphQL waarin het mode is om tijdens het opstarten van een SPA de hele dataset alvast in te laden en je hebt een recept voor een faal. Voeg daar dan nog aan toe dat GraphQL gebruik maakt van POST om de queries door te sturen, waardoor CraftCMS ook de resultaten niet meer wil cachen en je bent kaput.

Hoe moet het dan wel?

  1. Als je perse GraphQL wilt gebruiken, zet daar dan iets als Postgraphile of Hasura achter, die zijn in staat om de GraphQL query om te zetten naar een genestte JSON-query in PostgreSQL en dat is echt absurd veel sneller.
  2. Doe loadtests en principetests tijdens het ontwikkelen. Wacht niet tot je klaar bent want als je dan nog een probleem tegenkomt kun je er niets meer aan doen.
  3. NginX kan POST requests cachen.
  4. ORM is extreem handig voor CRUD en voltrekt bagger voor de rest. Leer SQL, leer wat je database allemaal kan en gebruik dat.
  5. Wees niet bang om custom code toe te passen. Binnen databases is het echt heel normaal om views en procedures te maken die specifiek zijn bedoeld om een tekortkoming van de applicatie op te vangen. Daar is niets mis mee, dat kun je gewoon doen.