{"id":21331,"date":"2026-09-12T15:01:49","date_gmt":"2026-09-12T13:01:49","guid":{"rendered":"https:\/\/webhosting.de\/mariadb-optimizer-trace-sql-performance-analyse-datenbank\/"},"modified":"2026-09-12T15:01:49","modified_gmt":"2026-09-12T13:01:49","slug":"mariadb-optimizer-trace-sql-ydeevneanalyse-database","status":"publish","type":"post","link":"https:\/\/webhosting.de\/da\/mariadb-optimizer-trace-sql-performance-analyse-datenbank\/","title":{"rendered":"MariaDB Optimizer Trace \u2013 S\u00e5dan forst\u00e5r du SQL-foresp\u00f8rgsler i detaljer"},"content":{"rendered":"<p>Med optimizer trace i MariaDB kan jeg trin for trin forst\u00e5, hvorfor optimizer v\u00e6lger en bestemt plan, og hvilke varianter den frav\u00e6lger. Dette JSON-spor viser mig <strong>Beslutninger<\/strong> om omkostninger, sammenk\u00e6dningsr\u00e6kkef\u00f8lger og filtrering, s\u00e5 jeg kan tilpasse SQL-foresp\u00f8rgsler m\u00e5lrettet.<\/p>\n\n<h2>Centrale punkter<\/h2>\n\n<ul>\n  <li><strong>Gennemsigtighed<\/strong>: En JSON-baseret oversigt forklarer omskrivninger, omkostninger og forkastede planer.<\/li>\n  <li><strong>Fokus<\/strong>: join_preparation og join_optimization giver de vigtigste indsigter.<\/li>\n  <li><strong>Kontrolsystem<\/strong>: Sessionsvariabler begr\u00e6nser overhead og hukommelsesforbrug.<\/li>\n  <li><strong>Arbejdsgang<\/strong>: EXPLAIN\/ANALYZE til at se planen, Trace til at finde ud af \u201ehvorfor\u201c.<\/li>\n  <li><strong>Praktiske fordele<\/strong>: Tilpas indekser, statistikker og sammenk\u00e6dningsr\u00e6kkef\u00f8lger p\u00e5 et velunderbygget grundlag.<\/li>\n<\/ul>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb-optimizer-trace-0294.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Hvad er MariaDB Optimizer Trace?<\/h2>\n\n<p>MariaDB har siden version 10.4 indf\u00f8rt en <strong>Optimering<\/strong> Trace, der dokumenterer hver st\u00f8rre optimeringsfase i en SELECT-, UPDATE- eller DELETE-s\u00e6tning som JSON. Her kan jeg se, hvordan motoren udvider foresp\u00f8rgsler, normaliserer betingelser og til sidst fastl\u00e6gger sammenk\u00e6dningsr\u00e6kkef\u00f8lgen samt indeksadgangene. Dette indblik g\u00e5r betydeligt dybere end EXPLAIN, der prim\u00e6rt viser slutplanen, og afsl\u00f8rer forkastede alternativer med begrundelser. Sporet ligger i hukommelsen for hver forbindelse og er tilg\u00e6ngeligt via <code>information_schema.OPTIMIZER_TRACE<\/code> klar. S\u00e5 f\u00e5r jeg en fuldst\u00e6ndig, maskinl\u00e6sbar beskrivelse af de interne <strong>Trin<\/strong>, som har f\u00f8rt til en gennemf\u00f8relsesplan.<\/p>\n\n<h2>Aktiv\u00e9r og udl\u00e6s Optimizer Trace<\/h2>\n\n<p>Jeg aktiverer funktionen m\u00e5lrettet for hver session, s\u00e5 jeg kan k\u00f8re diagnoser uden global overhead og har fuld kontrol over <strong>Hukommelse<\/strong> har. Normalt s\u00e6tter jeg <code>SET SESSION optimizer_trace = 'enabled=on';<\/code> og hvis det er n\u00f8dvendigt <code>SET SESSION optimizer_trace_max_mem_size = 1048576;<\/code> eller h\u00f8jere, hvis sporet bliver omfattende. Derefter k\u00f8rer jeg den mist\u00e6nkelige foresp\u00f8rgsel og l\u00e6ser sporet med <code>SELECT * FROM information_schema.OPTIMIZER_TRACE LIMIT 1\\G;<\/code>. Vigtigt: Tabellen gemmer kun den seneste foresp\u00f8rgsel fra den aktive forbindelse, og jeg tager h\u00f8jde for felter som <code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code> eller <code>INSUFFICIENT_PRIVILEGES<\/code> til diagnostiske oplysninger. Denne fremgangsm\u00e5de holder produktionsmilj\u00f8et str\u00f8mlinet og g\u00f8r analysen <strong>pr\u00e6cis<\/strong>.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Variabel\/felt<\/th>\n      <th>Form\u00e5l<\/th>\n      <th>Eksempel p\u00e5 v\u00e6rdi<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code>optimizer_trace<\/code><\/td>\n      <td>Aktiverer sporing pr. session<\/td>\n      <td><code>'enabled=on'<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code>optimizer_trace_max_mem_size<\/code><\/td>\n      <td>Maksimal lagerplads pr. spor<\/td>\n      <td><code>1048576<\/code> (1 MB)<\/td>\n    <\/tr>\n    <tr>\n      <td><code>OPTIMIZER_TRACE.QUERY<\/code><\/td>\n      <td>Oprindelig SQL-s\u00e6tning<\/td>\n      <td><code>SELECT ...<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code>OPTIMIZER_TRACE.TRACE<\/code><\/td>\n      <td>JSON-dokument om optimeringen<\/td>\n      <td>JSON-tekst<\/td>\n    <\/tr>\n    <tr>\n      <td><code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code><\/td>\n      <td>Bytes, der er blevet afsk\u00e5ret, n\u00e5r sporet er for stort<\/td>\n      <td>0 eller antal<\/td>\n    <\/tr>\n    <tr>\n      <td><code>INSUFFICIENT_PRIVILEGES<\/code><\/td>\n      <td>Er l\u00e6seadgangen tilstr\u00e6kkelig?<\/td>\n      <td>0 eller 1<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb_optimizer_besprechung_5829.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>JSON-struktur: join_preparation og join_optimization<\/h2>\n\n<p>JSON-strukturen er opdelt i f\u00f8lgende blokke <code>join_preparation<\/code> og <code>join-optimering<\/code>, som jeg gennemg\u00e5r f\u00f8rst, fordi de er de vigtigste <strong>Noter<\/strong> levere. I afsnittet <code>join_preparation<\/code> Jeg genkender den udvidede foresp\u00f8rgsel (<code>udvidet_s\u00f8gning<\/code>) og ser, om og hvordan motoren har omformet betingelser eller fremskrivninger. Den anden blok <code>join-optimering<\/code> registrerer linjeestimater, de gennemg\u00e5ede planer, den valgte sammenk\u00e6dningsr\u00e6kkef\u00f8lge og tilf\u00f8jelsen af selektive WHERE-dele til tabeller. Undertr\u00e6erne er s\u00e6rligt nyttige <code>rows_estimation<\/code>, <code>overvejede_udf\u00f8relsesplaner<\/code> og <code>tilknytning_af_betingelser_til_tabeller<\/code>, fordi de henviser direkte til omkostningsantagelser og filterpositioner. P\u00e5 den m\u00e5de kan jeg hurtigt se, hvor der er fejlvurderinger eller ugunstige <strong>Indekser<\/strong> f\u00f8re til suboptimale planer.<\/p>\n\n<h2>Sammenligning med EXPLAIN og ANALYZE<\/h2>\n\n<p>For at f\u00e5 en fuldst\u00e6ndig vurdering kombinerer jeg EXPLAIN, ANALYZE og <strong>Spor<\/strong> i en fast r\u00e6kkef\u00f8lge. F\u00f8rst bruger jeg <code>FORKLAR<\/code> eller <code>EXPLAIN FORMAT=JSON<\/code>, for at se den valgte plan og n\u00f8glebanerne. Derefter indstiller jeg <code>FORKLAR ANALYSE<\/code> for at f\u00e5 reelle k\u00f8rselstidsdata og t\u00e6llerv\u00e6rdier s\u00e5som loops og filtrerede linjer. Hvis der stadig er ubesvarede sp\u00f8rgsm\u00e5l, aktiverer jeg Optimizer Trace og ser, hvilke varianter optimeringsv\u00e6rkt\u00f8jet har unders\u00f8gt og afvist. Denne artikel giver mig en kortfattet introduktion til fortolkningen af <a href=\"https:\/\/webhosting.de\/da\/mysql-explain-analyze-fortolkning-af-foresporgsler-optimering-af-foresporgsler\/\">At forst\u00e5 EXPLAIN ANALYZE<\/a>, som jeg bruger som supplement, n\u00e5r det er n\u00f8dvendigt.<\/p>\n\n<h2>Forst\u00e5 planbeslutninger: Omkostninger, kardinaliteter, filtre<\/h2>\n\n<p>Beslutningslogikken bygger p\u00e5 kardinaliteter, omkostningsmodeller og placeringen af <strong>Filter<\/strong> i henhold til planen. I sporingen kan jeg for hver betragtet join-r\u00e6kkef\u00f8lge se, hvilke m\u00e6ngder af r\u00e6kker motoren forventer, og hvordan den udleder de samlede omkostninger heraf. Jeg kontrollerer, om for\u00e6ldede statistikker eller ugunstige korrelationer medf\u00f8rer, at range-scans undervurderes, og at full-scans foretr\u00e6kkes. Desuden unders\u00f8ger jeg, om motoren knytter WHERE-betingelser tidligt nok til den mest selektive tabel for at reducere dyre join-trin. P\u00e5 den m\u00e5de kan jeg komme med p\u00e5lidelige konklusioner om, hvorfor en plan blev valgt, og hvordan jeg kan optimere den med <strong>Indekser<\/strong>, omskrivninger eller opdatering af statistikker.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb-optimizer-trace-sql-4271.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Praksis: Spor en enkel filterforesp\u00f8rgsel<\/h2>\n\n<p>Med <code>SELECT * FROM t1 WHERE a &lt; 10<\/code> tjekker jeg under <code>join_preparation<\/code>, om motoren har udvidet projektionen og eventuelt konsolideret betingelserne, hvilket gav mig en f\u00f8rste <strong>Indikatorer<\/strong> leverer. Derefter ser jeg i blokken <code>rows_estimation<\/code>, hvor mange linjer motoren bruger til range-scan p\u00e5 <code>a<\/code> i forhold til en fuld tabelscanning. Hvis der findes urealistiske v\u00e6rdier, tolker jeg det ofte som et tegn p\u00e5 for\u00e6ldede statistikker eller manglende histogrammer. I afsnittet <code>overvejede_udf\u00f8relsesplaner<\/code> Derefter kan jeg se, om indeksadgangen virkelig er blevet beregnet til at v\u00e6re billigere end en fuld scanning. Til sidst viser <code>tilknytning_af_betingelser_til_tabeller<\/code>, om den selektive betingelse g\u00e6lder for <code>a<\/code> kommer tidligt i gang, hvilket reducerer l\u00f8betiden betydeligt <strong>s\u00e6nker<\/strong>.<\/p>\n\n<h2>JSON-funktioner: M\u00e5lrettet udtr\u00e6kning af uddrag<\/h2>\n\n<p>Da sporet foreligger som JSON, filtrerer jeg m\u00e5lrettet deltr\u00e6er med <code>JSON_EXTRACT<\/code> og udarbejder sm\u00e5 analyser af tilbagevendende <strong>Pr\u00f8ve<\/strong>. Jeg gennemg\u00e5r for eksempel blot listen over de overvejede planer for at kontrollere, om bestemte join-r\u00e6kkef\u00f8lger systematisk mislykkes. Ligeledes udtr\u00e6kker jeg omkostningsfelter fra de bedste kandidater og sammenligner dem med ANALYZE-data for at afd\u00e6kke fejlagtige antagelser. Ved hj\u00e6lp af enkle visninger eller gemte procedurer automatiserer jeg disse kontroller til mine diagnosesessioner. P\u00e5 denne m\u00e5de opbygger jeg et let <strong>Overv\u00e5gning<\/strong> til optimeringsbeslutninger uden at aktivere permanent sporing.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb_optimizer_trace_4729.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Typiske anvendelsestilf\u00e6lde og fordele<\/h2>\n\n<p>Jeg bruger Trace, n\u00e5r EXPLAIN viser en uventet fuld scanning, og jeg vil finde \u00e5rsagen til, at en <strong>Indeks<\/strong> vil finde ud af. Ligeledes giver sporingen mig for mange tabeller en begrundelse for den valgte r\u00e6kkef\u00f8lge af sammenkoblinger, hvilket viser mig vejen til alternative planer. Ved versionsskift gemmer jeg traces f\u00f8r og efter opdateringen for at kunne vurdere \u00e6ndringer i optimizerens adf\u00e6rd. I forbindelse med strategiske tuning-sp\u00f8rgsm\u00e5l hj\u00e6lper dette overblik mig med at <a href=\"https:\/\/webhosting.de\/da\/en-indgaende-forklaring-af-mariadbs-foresporgselsoptimerer-indsigt-i-sql-tuning\/\">interne optimeringsmekanismer<\/a>, som jeg knytter til sporingsresultaterne. P\u00e5 den m\u00e5de tr\u00e6ffer jeg en struktureret beslutning om, hvorvidt jeg skal justere indekser, statistikker eller formuleringen af foresp\u00f8rgslerne <strong>justeringsskrue<\/strong> s\u00e6t.<\/p>\n\n<h2>Bedste praksis inden for produktion<\/h2>\n\n<p>Jeg aktiverer sporing konsekvent som <strong>Session<\/strong>-Indstil og afslut diagnosen ordentligt, s\u00e5 snart jeg har nok data. Ved store spor \u00f8ger jeg <code>optimizer_trace_max_mem_size<\/code> kun kortvarigt, og indstiller v\u00e6rdien til et lavt niveau igen bagefter. Inden jeg deler JSON-filer, maskerer jeg f\u00f8lsomme konstanter, kommentartekster eller forretningsm\u00e6ssige n\u00f8gletal. Jeg bruger sporing m\u00e5lrettet som et diagnosticeringsv\u00e6rkt\u00f8j, mens jeg til l\u00f8bende overv\u00e5gning foretr\u00e6kker logfiler over langsomme foresp\u00f8rgsler, pr\u00e6stationsoversigter eller eksterne profilere. Denne disciplin holder systemerne str\u00f8mlinede og forhindrer un\u00f8dvendig <strong>Overhead<\/strong> i den daglige drift.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb_optimizer_trace_3874.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Optimizer Trace i v\u00e6rkt\u00f8jssamlingen<\/h2>\n\n<p>For at opn\u00e5 en helhedsorienteret optimering kortl\u00e6gger jeg k\u00e6den best\u00e5ende af forst\u00e5else af planen, \u00e5rsagsanalyse og systemm\u00e5ling og sammenk\u00e6der disse <strong>Resultater<\/strong>. EXPLAIN viser mig planen, ANALYZE bekr\u00e6fter de faktiske omkostninger, og sporet giver baggrunden for beslutningen. Samtidig ser jeg p\u00e5 koncepter inden for query-execution-plan for at kunne indordne m\u00f8nstre i n\u00f8glevalg, kardinaliteter og join-strategier. Et godt supplement til denne vinkel er det kompakte overblik over <a href=\"https:\/\/webhosting.de\/da\/planer-for-udforelse-af-databaseforesporgsler-hosting-optimering-performance-indsigt\/\">Planer for udf\u00f8relse af foresp\u00f8rgsler<\/a>, som jeg bruger som reference i arkitektoniske sp\u00f8rgsm\u00e5l. Herfra udleder jeg p\u00e5lidelige <strong>Prioriteringer<\/strong> til indeksering, omskrivninger og parametre.<\/p>\n\n<h2>Dyk dybere ned: range_analysis og valg af n\u00f8gler<\/h2>\n\n<p>Der er ofte en blok i sporet <code>range_analysis<\/code> for hver tabel, hvor jeg kan se, hvilke indekser der kom i betragtning til Range-, Ref- eller EQ-Ref-adgang. Optimizeren sammenligner her alternativer som \u201erange p\u00e5 idx_a\u201c, \u201erange p\u00e5 idx_b\u201c eller \u201efuld scanning\u201c, tildeler dem omkostninger og forventede r\u00e6kker og markerer vinderen. Hvis jeg ser, at et fornuftigt indeks er blevet forkastet p\u00e5 grund af h\u00f8je omkostninger, ser jeg som det n\u00e6ste p\u00e5 de underliggende selektiviteter og statistikker. Hvis antagelserne ikke stemmer, kan en <code>ANALYSE TABLE<\/code> (evt. med vedvarende statistik) eller oprettelsen af en mere m\u00e5lrettet <strong>D\u00e6kningsindeks<\/strong> omst\u00f8de afg\u00f8relsen.<\/p>\n\n<p>Det er ogs\u00e5 nyttigt at se p\u00e5 opdelinger af sammensatte indekser: Sporet dokumenterer, om betingelsen kun bruger indeksets f\u00f8rste kolonne, eller om yderligere pr\u00e6dikater kan anvendes, og andre n\u00f8glekolonner dermed bliver relevante. Ud fra dette afg\u00f8r jeg, om jeg skal omformulere pr\u00e6dikaterne (f.eks. undg\u00e5 funktioner) eller udvide indekset, s\u00e5 typiske filtreringer og sorteringer d\u00e6kkes.<\/p>\n\n<h2>Join-operationer i detaljer: Semijoins, BKA\/MRR og join-buffere<\/h2>\n\n<p>Ved foresp\u00f8rgsler p\u00e5 flere tabeller viser sporingsafsnittene, om og hvilken semijoin-strategi der er blevet overvejet (f.eks. FirstMatch, DuplicateWeedout, LooseScan eller Materialization). Der kan jeg se, hvorfor en variant blev forkastet \u2013 f.eks. p\u00e5 grund af h\u00f8je materialiseringsomkostninger eller for lav selektivitet. Ogs\u00e5 <strong>Batched Key Access (BKA)<\/strong> og <strong>L\u00e6sning af flere omr\u00e5der (MRR)<\/strong> vises i sporet, hvis de er aktiveret. Disse teknikker samler n\u00f8gleopslag og forbedrer cache-lokaliteten. Hvis BKA\/MRR ikke vises i sporet, tjekker jeg <code>optimizer_switch<\/code> og parametre som <code>join_cache_level<\/code>. I arbejdsbelastninger med mange tilf\u00e6ldige n\u00f8gleopslag kan join-fasen dermed fremskyndes m\u00e6rkbart, hvilket kan bekr\u00e6ftes med EXPLAIN ANALYZE.<\/p>\n\n<p>Desuden er st\u00f8rrelsen og typen af join-bufferen afg\u00f8rende: Sporing viser, om der er k\u00f8rt nested-loop-varianter med eller uden buffer, og hvor filtrene tr\u00e6der i kraft. Jeg vurderer, om yderligere indekser p\u00e5 join-n\u00f8gler eller en omskrivning for at reducere mellemsresultaterne er det mere effektive valg end at \u00f8ge bufferst\u00f8rrelserne.<\/p>\n\n<h2>Underforesp\u00f8rgsler, afledte tabeller og visninger<\/h2>\n\n<p>P\u00e5 <code>join_preparation<\/code> Jeg synes, at subforesp\u00f8rgsler i EXISTS\/IN-form i <strong>Semijoins<\/strong> blev omdannet (<code>in_to_exists<\/code>), om afledte tabeller er sammenlagt (<code>afledt_sammenfletning<\/code>) eller er blevet realiseret, og om <strong>Kondition Pushdown<\/strong> helt ned til afledte tabeller. Disse trin er afg\u00f8rende, fordi en manglende sammenfletning kan f\u00f8re til en kostbar materialisering. Hvis jeg i sporingloggen gentagne gange ser materialiseringsbeslutninger med h\u00f8je omkostninger, tester jeg, om en eksplicit <code>STRAIGHT_JOIN<\/code>, et tip eller en omstrukturering af foresp\u00f8rgslen (f.eks. Common Table Expressions med m\u00e5lrettede filtre) f\u00e5r motoren til at v\u00e6lge en mere effektiv strategi. N\u00e5r det g\u00e6lder visninger, tjekker jeg, om optimeringsv\u00e6rkt\u00f8jet opl\u00f8ser visningens indhold tilstr\u00e6kkeligt, eller om der mangler yderligere indekser i den underliggende tabel.<\/p>\n\n<h2>Partitionering og besk\u00e6ring<\/h2>\n\n<p>For partitionerede tabeller viser sporet, hvilke partitioner der er blevet udelukket p\u00e5 grundlag af partitionsn\u00f8gler og pr\u00e6dikater (<strong>Partitionsbesk\u00e6ring<\/strong>). Hvis den forventede pruning udebliver, er det et tegn p\u00e5, at filtrene b\u00f8r formuleres tidligere og p\u00e5 en m\u00e5de, der tager h\u00f8jde for partitionsn\u00f8glen. Jeg er desuden opm\u00e6rksom p\u00e5 samspillet mellem partitionering og indekser: Mangler der lokale eller globale indekser, kan motoren trods pruning tjekke et uforholdsm\u00e6ssigt stort antal r\u00e6kker, hvilket kan ses i sporet som h\u00f8je scanningsomkostninger.<\/p>\n\n<h2>M\u00e5lrettet verifikation af hints, indeksangivelser og optimizer_switch<\/h2>\n\n<p>Jeg bruger Trace til at unders\u00f8ge effekten af hints og parameteromskiftere for at <strong>bes\u00e6tte<\/strong>. Hvis jeg f.eks. s\u00e6tter. <code>FORCE-INDEKS<\/code> eller et optimeringsforslag kan jeg i sporingen se, om alternativet virkelig blev tvunget, og hvordan det blev vurderet. Via <code>optimizer_switch<\/code> kan jeg midlertidigt aktivere eller deaktivere strategier (f.eks. for semijoin-, index_merge- eller derived_merge-beslutninger). Trace-udskriften fungerer derefter som bevis for, om motoren har accepteret specifikationerne, eller om andre begr\u00e6nsninger (f.eks. kardinaliteter) fortsat er afg\u00f8rende. Valgfrit bruger jeg formateringsflag som <code>one_line<\/code> eller <code>end_markers<\/code> p\u00e5 <code>optimizer_trace<\/code>-streng for at tilpasse l\u00e6sbarheden til mit analysev\u00e6rkt\u00f8j.<\/p>\n\n<h2>Update\/DELETE og skrivestier<\/h2>\n\n<p>Optimizer Trace er ikke begr\u00e6nset til SELECT. Ved UPDATE- og DELETE-s\u00e6tninger kan jeg ogs\u00e5 se, hvordan adgangsveje v\u00e6lges, og om filtre tr\u00e6der i kraft tidligt nok til at holde antallet af ber\u00f8rte r\u00e6kker lavt. Jeg kontrollerer, om et WHERE-filter ikke er sargable, eller om et manglende indeks f\u00f8rer til en bred scanningsfase, inden den egentlige \u00e6ndring udf\u00f8res. Ud fra sporet kan jeg afg\u00f8re, om et kompakt indeks (f.eks. kun de n\u00f8dvendige kolonner) undg\u00e5r un\u00f8dvendige frem-og-tilbage-adgange og dermed reducerer l\u00e5sninger og logvolumen.<\/p>\n\n<h2>Sikkerhed, privilegier og foruddefinerede s\u00e6tninger<\/h2>\n\n<p>For at jeg kan l\u00e6se sporet fuldt ud, skal jeg have tilstr\u00e6kkelige objektrettigheder \u2013 hvis disse mangler, angiver feltet <code>INSUFFICIENT_PRIVILEGES<\/code> Begr\u00e6nsninger. I produktionsn\u00e6re scenarier bruger jeg derfor de samme loginoplysninger som applikationen eller en specielt autoriseret diagnosekonto. Ved forberedte s\u00e6tninger viser sporingstjenesten typisk allerede den optimerede form med bundne parametre, hvilket giver mig mulighed for at vurdere selektiviteter uden at afsl\u00f8re f\u00f8lsomme konstanter. Hvis jeg er n\u00f8dt til at dele sporingstjenester, maskerer jeg parameterv\u00e6rdier eller erstatter dem med repr\u00e6sentative intervaller for at overholde kravene til databeskyttelse.<\/p>\n\n<h2>Automatisering: Registrering, differentiering og dokumentation af spor<\/h2>\n\n<p>For at sikre reproducerbare analyser gemmer jeg spor stikpr\u00f8vevis i en diagnosetabel og forsyner dem med metadata s\u00e5som skema, version, sessionsvariabler og tidsstempler. P\u00e5 den m\u00e5de kan jeg f\u00f8r og efter indeks\u00e6ndringer eller versionsopgraderinger <strong>diffen<\/strong>, hvilke beslutninger der er blevet udsat. Det er praktisk at inddele blokkene <code>overvejede_udf\u00f8relsesplaner<\/code> og <code>rows_estimation<\/code> at gemme separat, s\u00e5 jeg hurtigt kan sammenligne \u00e6ndringer i omkostningerne. Mindre hj\u00e6lpeforesp\u00f8rgsler udtr\u00e6kker den valgte sammenk\u00e6dningsr\u00e6kkef\u00f8lge og de beregnede omkostninger \u2013 for eksempel med <code>JSON_EXTRACT(TRACE, '$.join_optimization.considered_execution_plans')<\/code> \u2013 og gemmer resultatet sammen med EXPLAIN- og ANALYZE-udskrifterne. P\u00e5 den m\u00e5de opst\u00e5r der en p\u00e5lidelig dokumentation for hvert optimeringstrin.<\/p>\n\n<h2>Begr\u00e6nsninger, versionsspecifikke egenskaber og sammenligning med MySQL<\/h2>\n\n<p>Tracens n\u00f8glestrukturer er baseret p\u00e5 MySQL, men detaljer og feltnavne kan variere en smule afh\u00e6ngigt af MariaDB-versionen. Derfor retter jeg min opm\u00e6rksomhed mod <strong>semantiske<\/strong> Afsnit (Rewrites, Rows-Estimation, betragtede planer, Condition-Attachments), i stedet for at lade mig irritere af kosmetiske forskelle. Vigtigt: I MariaDB er fokus p\u00e5 den sidste instruktion i den aktive forbindelse. Hvis man analyserer mange p\u00e5 hinanden f\u00f8lgende s\u00e6tninger, skal man derfor l\u00e6se dem umiddelbart efter udf\u00f8relsen eller automatisk via en hook, s\u00e5 ingen relevante spor overskrives. Ved meget store JSON-filer tager jeg h\u00f8jde for hukommelsesbehovet og forst\u00e5r <code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code> som en opfordring til midlertidigt at h\u00e6ve gr\u00e6nsen og k\u00f8re analysen igen.<\/p>\n\n<h2>Konkrete JSON-udtr\u00e6k til hverdagen<\/h2>\n\n<p>Til sidst et par korte uddrag, som jeg ofte bruger i praksis for hurtigt at komme til sagens kerne:<\/p>\n\n<ul>\n  <li>Valgt sammenk\u00e6dningsr\u00e6kkef\u00f8lge og kandidatlister: Jeg henter planpr\u00e6fikserne og den tilh\u00f8rende tabel for at kunne f\u00f8lge beslutningsforl\u00f8bet.<\/li>\n  <li>Range-alternativer og omkostninger: Jeg udtr\u00e6kker listen over de indekser, der er blevet vurderet, for de mest selektive tabeller, for m\u00e5lrettet at kunne vurdere omskrivninger eller nye indekser.<\/li>\n  <li>Filtre, der er tilf\u00f8jet tidligt: Jeg l\u00e6ser <code>tilknytning_af_betingelser_til_tabeller<\/code>-sektioner for at sikre, at st\u00e6rke pr\u00e6dikater placeres s\u00e5 t\u00e6t p\u00e5 datakilden som muligt.<\/li>\n<\/ul>\n\n<p>Med f\u00e5 visninger af disse udtr\u00e6k har jeg et overskueligt \u201eoverblik\u201c over optimeringsbeslutningerne, som jeg aktiverer efter behov under diagnosesessioner og derefter deaktiverer igen.<\/p>\n\n<h2>Hyppige snublesten og fejlfinding<\/h2>\n\n<p>Hvis der mangler histogrammer, eller hvis statistikkerne er for\u00e6ldede, er sk\u00f8nningerne forkerte og medf\u00f8rer <strong>Planer<\/strong> med un\u00f8dvendige fuldskanninger. Hvis jeg ser store afvigelser i kardinaliteterne i sporet, opdaterer jeg statistikkerne, opretter passende indekser eller omformulerer filtre, s\u00e5 de kan lagres. For korte spor genkender jeg ved hj\u00e6lp af <code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code> og reagerer med en midlertidigt h\u00f8jere gr\u00e6nse. Hvis ANALYZE giver bedre k\u00f8retider for en alternativ rute, tjekker jeg i sporing, hvilken omkostningsfaktor der har gjort den valgte variant til den foretrukne. P\u00e5 den m\u00e5de udfylder jeg trin for trin hullerne i min viden og opn\u00e5r <strong>Klarhed<\/strong> om beslutningslogikken.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb-optimizer-trace-4829.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Kort opsummeret<\/h2>\n\n<p>MariaDB Optimizer Trace forklarer mig i et JSON-dokument, hvordan motoren omformer foresp\u00f8rgsler, estimerer r\u00e6kker, sammenligner planer og til sidst en <strong>Sekvens<\/strong> v\u00e6lger. Jeg aktiverer den pr. session, l\u00e6ser sporet ud, kontrollerer <code>join_preparation<\/code> og <code>join-optimering<\/code> og kobler disse indsigter sammen med EXPLAIN\/ANALYZE. Ud fra \u00e5rsagerne til afviste indekser, forsinkede filtre eller fejlagtige sk\u00f8n udleder jeg konkrete tiltag: bedre indekser, mere opdaterede statistikker og klare formuleringer af foresp\u00f8rgsler. Ved hj\u00e6lp af JSON-funktioner udtr\u00e6kker jeg uddrag, genkender m\u00f8nstre og dokumenterer beslutninger p\u00e5 en reproducerbar m\u00e5de. P\u00e5 den m\u00e5de sikrer jeg, at selv omfattende SQL-arbejdsbelastninger udf\u00f8res p\u00e5lideligt <strong>Str\u00f8m<\/strong> og s\u00f8rg for, at beslutninger om tuning er gennemsigtige.<\/p>","protected":false},"excerpt":{"rendered":"<p>L\u00e6r, hvordan du bruger MariaDB Optimizer Trace til analyse og optimering af komplekse SQL-foresp\u00f8rgsler. Artiklen forklarer, hvordan du aktiverer, forst\u00e5r JSON-strukturen og fortolker optimizer trace for at opn\u00e5 bedre ydeevne.<\/p>","protected":false},"author":1,"featured_media":21324,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[781],"tags":[],"class_list":["post-21331","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-datenbanken-administration-anleitungen"],"acf":[],"_wp_attached_file":null,"_wp_attachment_metadata":null,"litespeed-optimize-size":null,"litespeed-optimize-set":null,"_elementor_source_image_hash":null,"_wp_attachment_image_alt":null,"stockpack_author_name":null,"stockpack_author_url":null,"stockpack_provider":null,"stockpack_image_url":null,"stockpack_license":null,"stockpack_license_url":null,"stockpack_modification":null,"color":null,"original_id":null,"original_url":null,"original_link":null,"unsplash_location":null,"unsplash_sponsor":null,"unsplash_exif":null,"unsplash_attachment_metadata":null,"_elementor_is_screenshot":null,"surfer_file_name":null,"surfer_file_original_url":null,"envato_tk_source_kit":null,"envato_tk_source_index":null,"envato_tk_manifest":null,"envato_tk_folder_name":null,"envato_tk_builder":null,"envato_elements_download_event":null,"_menu_item_type":null,"_menu_item_menu_item_parent":null,"_menu_item_object_id":null,"_menu_item_object":null,"_menu_item_target":null,"_menu_item_classes":null,"_menu_item_xfn":null,"_menu_item_url":null,"_trp_menu_languages":null,"rank_math_primary_category":null,"rank_math_title":null,"inline_featured_image":null,"_yoast_wpseo_primary_category":null,"rank_math_schema_blogposting":null,"rank_math_schema_videoobject":null,"_oembed_049c719bc4a9f89deaead66a7da9fddc":null,"_oembed_time_049c719bc4a9f89deaead66a7da9fddc":null,"_yoast_wpseo_focuskw":null,"_yoast_wpseo_linkdex":null,"_oembed_27e3473bf8bec795fbeb3a9d38489348":null,"_oembed_c3b0f6959478faf92a1f343d8f96b19e":null,"_trp_translated_slug_en_us":null,"_wp_desired_post_slug":null,"_yoast_wpseo_title":null,"tldname":null,"tldpreis":null,"tldrubrik":null,"tldpolicylink":null,"tldsize":null,"tldregistrierungsdauer":null,"tldtransfer":null,"tldwhoisprivacy":null,"tldregistrarchange":null,"tldregistrantchange":null,"tldwhoisupdate":null,"tldnameserverupdate":null,"tlddeletesofort":null,"tlddeleteexpire":null,"tldumlaute":null,"tldrestore":null,"tldsubcategory":null,"tldbildname":null,"tldbildurl":null,"tldclean":null,"tldcategory":null,"tldpolicy":null,"tldbesonderheiten":null,"tld_bedeutung":null,"_oembed_d167040d816d8f94c072940c8009f5f8":null,"_oembed_b0a0fa59ef14f8870da2c63f2027d064":null,"_oembed_4792fa4dfb2a8f09ab950a73b7f313ba":null,"_oembed_33ceb1fe54a8ab775d9410abf699878d":null,"_oembed_fd7014d14d919b45ec004937c0db9335":null,"_oembed_21a029d076783ec3e8042698c351bd7e":null,"_oembed_be5ea8a0c7b18e658f08cc571a909452":null,"_oembed_a9ca7a298b19f9b48ec5914e010294d2":null,"_oembed_f8db6b27d08a2bb1f920e7647808899a":null,"_oembed_168ebde5096e77d8a89326519af9e022":null,"_oembed_cdb76f1b345b42743edfe25481b6f98f":null,"_oembed_87b0613611ae54e86e8864265404b0a1":null,"_oembed_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_oembed_time_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_tldname":null,"_tldclean":null,"_tldpreis":null,"_tldcategory":null,"_tldsubcategory":null,"_tldpolicy":null,"_tldpolicylink":null,"_tldsize":null,"_tldregistrierungsdauer":null,"_tldtransfer":null,"_tldwhoisprivacy":null,"_tldregistrarchange":null,"_tldregistrantchange":null,"_tldwhoisupdate":null,"_tldnameserverupdate":null,"_tlddeletesofort":null,"_tlddeleteexpire":null,"_tldumlaute":null,"_tldrestore":null,"_tldbildname":null,"_tldbildurl":null,"_tld_bedeutung":null,"_tldbesonderheiten":null,"_oembed_ad96e4112edb9f8ffa35731d4098bc6b":null,"_oembed_8357e2b8a2575c74ed5978f262a10126":null,"_oembed_3d5fea5103dd0d22ec5d6a33eff7f863":null,"_eael_widget_elements":null,"_oembed_0d8a206f09633e3d62b95a15a4dd0487":null,"_oembed_time_0d8a206f09633e3d62b95a15a4dd0487":null,"_aioseo_description":null,"_eb_attr":null,"_eb_data_table":null,"_oembed_819a879e7da16dd629cfd15a97334c8a":null,"_oembed_time_819a879e7da16dd629cfd15a97334c8a":null,"_acf_changed":null,"_wpcode_auto_insert":null,"_edit_last":null,"_edit_lock":null,"_oembed_e7b913c6c84084ed9702cb4feb012ddd":null,"_oembed_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_time_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_03514b67990db061d7c4672de26dc514":null,"_oembed_time_03514b67990db061d7c4672de26dc514":null,"rank_math_news_sitemap_robots":null,"rank_math_robots":null,"_eael_post_view_count":"62","_trp_automatically_translated_slug_ru_ru":null,"_trp_automatically_translated_slug_et":null,"_trp_automatically_translated_slug_lv":null,"_trp_automatically_translated_slug_fr_fr":null,"_trp_automatically_translated_slug_en_us":null,"_wp_old_slug":null,"_trp_automatically_translated_slug_da_dk":null,"_trp_automatically_translated_slug_pl_pl":null,"_trp_automatically_translated_slug_es_es":null,"_trp_automatically_translated_slug_hu_hu":null,"_trp_automatically_translated_slug_fi":null,"_trp_automatically_translated_slug_ja":null,"_trp_automatically_translated_slug_lt_lt":null,"_elementor_edit_mode":null,"_elementor_template_type":null,"_elementor_version":null,"_elementor_pro_version":null,"_wp_page_template":null,"_elementor_page_settings":null,"_elementor_data":null,"_elementor_css":null,"_elementor_conditions":null,"_happyaddons_elements_cache":null,"_oembed_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_time_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_time_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_59808117857ddf57e478a31d79f76e4d":null,"_oembed_time_59808117857ddf57e478a31d79f76e4d":null,"_oembed_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_time_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_81002f7ee3604f645db4ebcfd1912acf":null,"_oembed_time_81002f7ee3604f645db4ebcfd1912acf":null,"_elementor_screenshot":null,"_oembed_7ea3429961cf98fa85da9747683af827":null,"_oembed_time_7ea3429961cf98fa85da9747683af827":null,"_elementor_controls_usage":null,"_elementor_page_assets":[],"_elementor_screenshot_failed":null,"theplus_transient_widgets":null,"_eael_custom_js":null,"_wp_old_date":null,"_trp_automatically_translated_slug_it_it":null,"_trp_automatically_translated_slug_pt_pt":null,"_trp_automatically_translated_slug_zh_cn":null,"_trp_automatically_translated_slug_nl_nl":null,"_trp_automatically_translated_slug_pt_br":null,"_trp_automatically_translated_slug_sv_se":null,"rank_math_analytic_object_id":null,"rank_math_internal_links_processed":"1","_trp_automatically_translated_slug_ro_ro":null,"_trp_automatically_translated_slug_sk_sk":null,"_trp_automatically_translated_slug_bg_bg":null,"_trp_automatically_translated_slug_sl_si":null,"litespeed_vpi_list":null,"litespeed_vpi_list_mobile":null,"rank_math_seo_score":null,"rank_math_contentai_score":null,"ilj_limitincominglinks":null,"ilj_maxincominglinks":null,"ilj_limitoutgoinglinks":null,"ilj_maxoutgoinglinks":null,"ilj_limitlinksperparagraph":null,"ilj_linksperparagraph":null,"ilj_blacklistdefinition":null,"ilj_linkdefinition":null,"_eb_reusable_block_ids":null,"rank_math_focus_keyword":"optimizer trace","rank_math_og_content_image":null,"_yoast_wpseo_metadesc":null,"_yoast_wpseo_content_score":null,"_yoast_wpseo_focuskeywords":null,"_yoast_wpseo_keywordsynonyms":null,"_yoast_wpseo_estimated-reading-time-minutes":null,"rank_math_description":null,"surfer_last_post_update":null,"surfer_last_post_update_direction":null,"surfer_keywords":null,"surfer_location":null,"surfer_draft_id":null,"surfer_permalink_hash":null,"surfer_scrape_ready":null,"_thumbnail_id":"21324","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/21331","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/comments?post=21331"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/21331\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media\/21324"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media?parent=21331"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/categories?post=21331"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/tags?post=21331"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}