...

WordPress-forespørgselscache: Hvorfor den normalt gør mere skade end gavn

Der WordPress Query Cache lover kortere indlæsningstider, men forårsager i praksis ofte ugyldiggørelser, Forsinkelse og inkonsekvent indhold. Jeg vil vise dig, hvorfor denne cache ofte æder ydeevnen i WordPress-opsætninger, og hvordan jeg kan opnå stabil hastighed i stedet.

Centrale punkter

  • InvalideringHyppige skriveoperationer tømmer cachen og genererer overhead.
  • ForsinkelseEksterne cacher tilføjer forbindelsestid, som ofte æder alle besparelser op.
  • UoverensstemmelseForældede indtastninger fører til gamle priser, forkerte lister eller tomme indkøbskurve.
  • RAM: Cachen konkurrerer med PHP, MySQL og Nginx/Apache om hukommelsen.
  • AlternativerSidecaching, OPcache og rene forespørgsler giver pålidelig profit.

Sådan fungerer WordPress' forespørgselscache virkelig

MySQL gemmer resultaterne af SELECT-forespørgsler ved hjælp af den nøjagtige SQL-tekst i Cache og leverer den igen med en identisk forespørgsel og sparer dermed udførelsen. I WordPress modtages INSERTs, UPDATEs og DELETEs imidlertid løbende, hvilket straks indlæser forespørgselscachen for de berørte tabeller. handicappede. Jeg ser jævnligt en endeløs løkke i logfiler: fyld, tøm, fyld igen - serveren brænder CPU-tid af uden nogen mærkbar fordel. Derudover kolliderer MySQL-forespørgselscachen med WordPress' egne mekanismer som transienter og objektcachen, hvilket øger ventetiden i stedet for at reducere den. De, der aktiverer WordPress-forespørgselscachen, opbygger derfor ofte et dobbelt cachelag, der går i stykker hurtigere, end det kan bære.

Definition: Hvad er det egentlig, der caches her?

Jeg skelner mellem tre niveauer, som ofte blandes sammen:

  • MySQL Query CacheResultatcache for identiske SELECT-sætninger. Hver skriveoperation til berørte tabeller ugyldiggør poster. Dette er kontraproduktivt i moderne OLTP-arbejdsbelastninger som WordPress. I nyere MySQL-versioner er denne cache også forældet; den findes stadig i MariaDB, men der slår jeg den også fra.
  • InnoDB-bufferpulje: Ikke en resultatcache, men en sidecache til data- og indekssider. Det er den robuste, gennemprøvede vej til tilbagevendende læseadgange. En solid bufferpuljestørrelse giver ofte mere end nogen resultatcache.
  • WordPress-objektcache/transienterCache på applikationssiden (ofte Redis/Memcached), hvor forberedte strukturer som WP_Query-resultater, optioner eller HTML-fragmenter gemmes. Dette lag hjælper kun, hvis læseadgang er reglen, og ugyldiggørelse fungerer pålideligt.

I hverdagen har jeg observeret, at bufferpuljen og en velvalgt sidecache er de største løftestænger. Yderligere caching af forespørgsler giver sjældent en nettogevinst, men øger kompleksiteten, ventetiden og risikoen for uoverensstemmelser.

Hvorfor det bremser i stedet for at hjælpe

På delte hosts eller med WooCommerce genererer cachen mærkbar Forsinkelse, fordi hver netværksforbindelse til Redis eller Memcached koster tid og næsten ikke giver nogen hits. Selv på hurtige maskiner mister jeg ofte millisekunder pr. anmodning, som vokser med trafikken og øger time-to-first-bytes. Derudover er der risiko for forældede resultater, hvis der mangler invalidation hooks, eller plugins fungerer forkert - pludselig ser en kunde et forkert resultat. Pris eller missede aktier. Hvis du vil se nærmere på det, anbefaler jeg min erfaringsrapport Object Cache-bremser fordi lignende mønstre gælder for cachelagring af forespørgsler. I gennemsnit opnår ren direkte adgang til databasen med et godt skema og OPcache bedre og mere stabile svartider.

Cache-stampede, TTL og koordinering

Et tilbagevendende mønster i WordPress-stakke er Cache-stampedeEn post udløber, mange forespørgsler foretager den samme dyre forespørgsel på samme tid og skaber spidsbelastninger. Forespørgsels- og objektcacher uden koordinering forværrer dette. Jeg bruger tre strategier for at undgå dette:

  • Låsning/koalescens: En anmodning opbygger posten, de andre venter kort eller returnerer den gamle værdi (stale-while-revalidate) og opdateres i baggrunden.
  • Nyttige TTL'erIngen vilkårlige 24-timers standarder. Produktlister eller prisfragmenter får korte TTL'er (sekunder/minutter), katalogmetadata længere.
  • Begivenhedsbaseret ugyldiggørelseI stedet for stumpe tidssekvenser bruger jeg hooks (f.eks. til post-opdateringer) til kun at slette berørte nøgler - eller bedre: til specifikt at forny sidecachen.

Vigtigt: I WordPress Transienter Effektivt med aktiv vedvarende objektcache permanent gemt. Hvis du ikke har en ren ugyldiggørelse her, vil du skabe inkonsistenser og fejlmønstre, som er svære at reproducere.

Typiske symptomer på produktive steder

Når WordPress' forespørgselscache er beskadiget, kan jeg først se det på en svingende Svartid, som pludselig går op og ned uden nogen kodeændringer. Om aftenen, når der kommer flere ordrer ind, hober ugyldiggørelserne sig op, og siden falder ind i en spiral af cache-misses og nye indtastninger. Overvågningen viser derefter ustabile CPU-toppe i MySQL, mens PHP-FPM venter på nye resultater. Samtidig rapporterer kunder om uoverensstemmelser såsom duplikerede kommentarer, tomme indkøbskurve eller forsinkede opdateringer af produktwidgets. Der dukker også i stigende grad låseadvarsler op i logfiler, fordi konkurrerende processer konstant skriver til de samme tabeller og dermed ugyldiggør cachen.

Cachelagringsniveauer: sekvens i stedet for stabling

Jeg prioriterer cacher efter effektkæde:

  1. Browser/CDN/edge-cache for fuldt offentlige sider, differentieret efter cookies/headers.
  2. Side-cache i stakken (webserver/plugin), ideelt set med forudindlæsning og målrettet rensning ved hændelser.
  3. OPcache for konsekvent kompileret PHP-bytecode.
  4. Objekt-cache kun selektivt for dyre, sjældent skiftende objekter.
  5. Database med et stærkt skema, indekser og en stor bufferpulje.

De, der holder sig til denne sekvens, reducerer ikke kun TTFB, men frem for alt varians - hvad brugerne opfatter som „ryk“.

Bedre muligheder for reel hastighed

Jeg får pålidelig performance, når jeg først Caching af sider Aktiver sidecaching, konfigurer OPcache korrekt, og strømlin derefter databaseforespørgsler. Sidecaching leverer HTML, reducerer databasebelastningen til nul og udjævner belastningstoppe. OPcache kompilerer PHP én gang, hvilket betyder, at PHP-FPM skal udføre mindre arbejde, og TTFB reduceres. En objektbaseret cache med Redis kan kun betale sig, hvis der er rigeligt med serverressourcer til rådighed, og applikationslogikken genererer få skriveadgange pr. side. Med denne sekvens eliminerer jeg flaskehalse ved kilden og holder antallet af bevægelige dele håndterbart i stedet for at bruge en skrøbelig buffer at vedligeholde.

Mål Vigtigste fordele Risiko/specialitet
Caching af sider (statisk HTML) Meget lav TTFB, Næsten ingen DB-belastning Indholdet skal opdateres specifikt, når der foretages ændringer
OPcache (PHP bytecode) Mindre CPU-tid pr. Anmodning Kræver konsekvent udrulning og opvarmningsstrategi
Redis objekt-cache Hurtig adgang til hyppige Objekter Hjælper kun med hits; æder RAM, har brug for et rent nøgledesign
MySQL Query Cache Teoretisk set mindre udførelse af forespørgsler Høj ugyldiggørelsesindsats, risiko for inkonsistens, ekstra overhead

Praktisk guide: Deaktiver og test alternativer

Jeg starter med MySQL og slår forespørgselscachen fra på systemniveau ved at ændre konfigurationen til query_cache_type0 og query_cache_size0 sæt. Derefter rydder jeg op i WordPress: Hvis et drop-in eller en konstant tvinger objektcaching, deaktiverer jeg det som en test med define('WP_CACHE', false);. Derefter bruger jeg værktøjer som Query Monitor, Blackfire eller simple metrikker (TTFB, forespørgsler/anmodninger, CPU) til at måle den faktiske påvirkning pr. side. Først når sidecaching er indstillet, og PHP/OPcache kører korrekt, vurderer jeg specifikt, om et lille Redis-lag aflaster belastningen på de enkelte hotspots. Denne sekvens giver mig reproducerbare resultater og sikrer Stabilitet, i stedet for at håbe på tilfældige hits.

Konkrete konfigurationer, der har bevist deres værd

Et par standardindstillinger, som jeg regelmæssigt opnår stabile gevinster med (valider altid på dit eget system):

  • MySQL/MariaDB:
    [mysqld]
    query_cache_type=0
    query_cache_size=0
    innodb_buffer_pool_size=60-70%_vom_RAM
    innodb_flush_log_at_trx_commit=1
    slow_query_log=1
    lang_forespørgsel_tid=0.2
    log_queries_not_using_indexes=1
        
    Bufferpuljen bærer den største belastning. Jeg viser den langsomme log til udviklerne og fjerner systematisk N+1 og SELECT *-mønstre.
  • OPcache:
    opcache.enable=1
    opcache.memory_consumption=256
    opcache.interned_strings_buffer=16
    opcache.max_accelerated_files=100000
    opcache.validate_timestamps=1
    opcache.revalidate_freq=60
    ; JIT for klassiske WordPress-stakke er snarere slået fra:
    opcache.jit=0
        
    En konsekvent udrulning (f.eks. atomare symlinks) og en opvarmning efter udgivelser er vigtig.
  • PHP-FPM:
    pm=dynamisk
    pm.max_children=.
    pm.max_requests=500-1000
    process_idle_timeout=10s
        
    Det dæmper lækager og fragmentering uden at fremprovokere koldstart.
  • Redis (hvis brugt):
    maxmemory .
    maxmemory-policy flygtig-lru
    tcp-backlog 511
    ; lokalt foretrukket via UNIX-socket for minimal ventetid
        
    Jeg accepterer kun Redis lokalt eller i samme AZ/host - over langsomme netværk bliver det hurtigt en latensforstærker.

Hold databasen ren: Indekser, forespørgsler, plugins

Før jeg stabler cacher, optimerer jeg forespørgsler og Indekser, fordi den største tidsbesparelse kommer fra godt dataarbejde. Overlange JOINs, SELECT *, manglende WHERE-betingelser og sortering uden indeks koster mere tid, end nogen cache kan spare. Jeg tjekker jævnligt plugins, der gemmer en masse indstillinger i wp_options uden en autoload-strategi, og fjerner overflødige udvidelser. En målrettet hjælp kan være at se og strømline dine egne SQL-mønstre - en introduktion findes hos Optimer databaseforespørgsler. Med ren forespørgselsdisciplin mindskes presset på serveren målbart, og den formodede fordel ved WordPress-forespørgselscachen tager sig af sig selv, fordi der ikke er noget tilbage at skjule.

Hosting-faktorer, der slår caching

God CPUYdeevne, hurtige NVMe SSD'er, tilstrækkeligt med RAM og de nyeste MySQL-versioner gør en større forskel end en skrøbelig forespørgselscache. Webserverens konfiguration spiller også en stor rolle: keep-alive, HTTP/2 eller HTTP/3, fornuftige timeouts og en slank PHP-procespulje. Jeg sørger for, at OPcache er generøst dimensioneret, så bytekoden i de hyppige scripts passer helt ind. Samtidig begrænser jeg cron-jobs og baggrundsopgaver, der udløser forespørgselsstorme i spidsbelastningsperioder. Det skaber en solid basisydelse, hvor jeg kan bruge sidecaching og målrettet objektcaching med stor nøjagtighed uden at gå i stå i skrøbelige Workarounds at tabe.

Målemetoder: Hvordan jeg vurderer effekten

Først måler jeg Baseline uden query cache: koldstart, varmstart, derefter 50 til 200 forespørgsler med JMeter eller k6. Derefter aktiverer jeg kun én justeringsskrue, aldrig flere på samme tid, og gentager belastningstestene. Jeg registrerer målinger som TTFB, P95/P99-latency, forespørgsler pr. anmodning, cache-hitrater og CPU/IO-værdier. En virkelig gevinst for mig er, når medianen og P95 falder, fejlraten falder, og variansen bliver mindre. I stort set alle WordPress-projekter viser denne metode, at WordPress Query Cache øger variansen og reducerer gennemsnittet Svarværdi forringet.

Tuning-playbook: Tærskler og kontroller

  • TræfprocentUnder ~60% objektcache-hits på produktiv trafik er det sjældent det værd. Så deaktiverer jeg konsekvent og måler igen.
  • Redis-latenstid>1 ms median lokalt er for meget. Sub-millisekunder kan opnås via UNIX-socket og kort pipeline.
  • DB-ventetiderRejser sig Tråde_løber stiger markant under belastning, tjekker jeg først indekser/forespørgsler - skruer ikke op for cachen.
  • varians: En faldende P95 er vigtigere for mig end en kosmetisk bedre medianstatistik.
  • Invalideringer: Ved hver indholds- eller prisopdatering ser jeg, hvor mange nøgler der forsvinder. Brede sletninger er et anti-mønster.
  • Opvarmning: Efter udrulninger/sideoprydninger forvarmer jeg automatisk kritiske ruter (startside, kategori, kasse).

Kompatibilitet og risici med plugins

Nogle udvidelser overskriver cachenøgler, rydder transienter for tidligt eller ignorerer nødvendige cachenøgler. Kroge, hvilket fører til forældreløse poster. Problemerne bliver mere synlige i multisite-miljøer, fordi flere skrivehændelser sker parallelt, og ugyldiggørelsen sker oftere. E-handelsworkflows med dynamiske priser, vouchers og indkøbskurvsfragmenter er særligt følsomme: Selv et par millisekunders forsinkelse kan vælte checkout-metrics. Jeg isolerer derfor caching-problemer ved gradvist at deaktivere plugins og verificere dem på klare målepunkter. Hvis et add-on kræver query-cache, undlader jeg det og vælger en løsning, der fungerer uden sårbarhed. Mellemliggende lag fungerer rent.

Driftssikkerhed: tilbagerulning og vedligeholdelse

Jeg sørger for, at ændringer i cachen kan rulles tilbage. Det betyder: funktionsflag for objekt-/sidecache, separate konfigurationsfiler og en tjekliste til nødsituationer. Hvis noget går galt under belastning, trækker jeg først query-/objektcachen ud og lader sidecachen + OPcache arbejde. Og derefter:

  1. Flush målrettet i stedet for globalt: Slet kun de berørte nøgler, tøm ikke hele Redis.
  2. Brug WP-CLI:
    wp cache flush
    wp transient delete --all
        
    Gem målingerne på forhånd, og mål så igen.
  3. Rotér træstammerne og langsom forespørgselslog i stedet for at slå cache-kontrollen til.

Kort resumé: Hvad jeg ansætter og hvorfor

Jeg slukker for WordPress' forespørgselscache på grund af ugyldiggørelse, Forsinkelse og inkonsekvens æder den teoretiske fortjeneste op. I stedet stoler jeg på sidecaching, OPcache og rent databasearbejde, der leverer konsekvent og uden overraskelser. Jeg bruger Redis selektivt, hvis der er et klart hotspot, og der er tilstrækkeligt med RAM til rådighed. Hvis man måler objektivt, bliver man hurtigt klar over, at velstrukturerede forespørgsler, stærke værtsressourcer og HTML-caching giver de rolige, hurtige svar, som ethvert websted har brug for. På den måde kan jeg planlægge performance, spare serveromkostninger i euro og undgå fejlmønstre, som ikke kan opfanges pålideligt med nogen forespørgselscache.

Aktuelle artikler