{"id":21018,"date":"2026-08-26T11:48:58","date_gmt":"2026-08-26T09:48:58","guid":{"rendered":"https:\/\/webhosting.de\/mysql-histograms-bessere-query-plaene-ohne-index-optimizer\/"},"modified":"2026-08-26T11:48:58","modified_gmt":"2026-08-26T09:48:58","slug":"mysql-histogrammer-giver-bedre-foresporgselsplaner-uden-indeksoptimerer","status":"publish","type":"post","link":"https:\/\/webhosting.de\/da\/mysql-histograms-bessere-query-plaene-ohne-index-optimizer\/","title":{"rendered":"MySQL-histogrammer \u2013 Bedre foresp\u00f8rgselsplaner uden indeks"},"content":{"rendered":"<p><strong>MySQL-histogrammer<\/strong> giver optimeringsmodulet reelle fordelingsdata, s\u00e5 den kan estimere selektiviteter korrekt og udarbejde hurtigere foresp\u00f8rgselsplaner \u2013 ofte endda uden et ekstra indeks. Jeg viser, hvordan jeg opretter og kontrollerer histogrammer i MySQL 8+ med ANALYZE TABLE og bruger dem til at tr\u00e6ffe bedre beslutninger ved sammenf\u00f8jninger, filtreringer og scanninger.<\/p>\n\n<h2>Centrale punkter<\/h2>\n<p><strong>Kort fokus<\/strong>: De f\u00f8lgende punkter viser, hvad jeg l\u00e6gger s\u00e6rlig v\u00e6gt p\u00e5, n\u00e5r jeg bruger histogrammer.<\/p>\n<ul>\n  <li><strong>Selektivitet<\/strong> I stedet for mavefornemmelse: mere realistiske sk\u00f8n over kardinalitet<\/li>\n  <li><strong>Uden indeks<\/strong> hurtigere: bedre valg af plan ved sk\u00e6ve fordelinger<\/li>\n  <li><strong>typer<\/strong> Forst\u00e5: M\u00e5lrettet brug af Singleton og Equi-Height<\/li>\n  <li><strong>Spande<\/strong> skat: Afvejning af afvikling mod omkostninger til metadata<\/li>\n  <li><strong>Pleje<\/strong> I fokus: Opdater, kontroller og slet om n\u00f8dvendigt<\/li>\n<\/ul>\n\n<h2>Hvorfor histogrammer uden indeks virker<\/h2>\n<p>Jeg bruger <strong>Histogrammer<\/strong>, fordi optimeringsmodulet ellers ofte antager en j\u00e6vn fordeling og dermed v\u00e6lger d\u00e5rlige planer. Et histogram viser <strong>V\u00e6rdifordeling<\/strong> den n\u00e6rmer sig en kolonne og leverer dermed realistiske selektivitetsestimater for pr\u00e6dikater som =, &gt;, BETWEEN, IN eller IS NULL. Optimeringsmodulet beslutter derefter, om en indeks-range-scanning, en tabelscanning eller en sammenf\u00f8jningsstrategi med indlejrede sl\u00f8jfer er mest fordelagtig. Hvis en betingelse f.eks. kun rammer 0,1 % af r\u00e6kkerne, foretr\u00e6kker jeg en m\u00e5lrettet adgang frem for en bred scanning. Hvis et filter derimod d\u00e6kker n\u00e6sten alle r\u00e6kker, undg\u00e5r jeg dyre indeksadgange, der ikke giver nogen fordel, og \u00f8ger dermed <strong>Effektivitet<\/strong> hver plan.<\/p>\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\/08\/mysql-query-histograms-6793.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Histogramtyper i MySQL 8.0<\/h2>\n<p>Jeg skelner mellem to <strong>typer<\/strong>: Singleton og Equi-Height. Singleton-histogrammer samler hyppigt forekommende enkeltv\u00e6rdier i separate kategorier \u2013 ideelt til kolonner med f\u00e5 dominerende kategorier som \u201eaktiv\u201c, \u201einaktiv\u201c eller \u201earkiveret\u201c. Equi-Height-histogrammer opdeler v\u00e6rdiomr\u00e5det p\u00e5 en s\u00e5dan m\u00e5de, at hver kategori indeholder omtrent det samme antal <strong>Linjer<\/strong> indeholder; dette egner sig til kontinuerlige eller uregelm\u00e6ssige fordelinger s\u00e5som priser, tidsstempler eller \u201ehullet\u201c ID-intervaller. Begge varianter giver optimeringsv\u00e6rkt\u00f8jet mere pr\u00e6cise hitprocenter for filtre. Jeg v\u00e6lger altid typen ud fra dataegenskaberne, ikke ud fra personlig pr\u00e6ference.<\/p>\n\n<h2>Tekniske grundlag: Styring af typevalg i MySQL<\/h2>\n<p>MySQL bestemmer den konkrete <strong>Histogramvariant<\/strong> automatisk p\u00e5 baggrund af datadistributionen. I praksis betyder det: Hvis antallet af forskellige v\u00e6rdier (NDV) er lille nok i forhold til antallet af buckets, opst\u00e5r der reelt et singleton-histogram; ellers genereres der et equi-height-histogram. Jeg \u201ev\u00e6lger\u201c derfor typen <em>indirekte<\/em>, ved at fastl\u00e6gge den relevante kolonne og et passende antal kategorier. For kolonner med meget f\u00e5, men st\u00e6rkt dominerende kategorier indstiller jeg bevidst f\u00e5 buckets for at opn\u00e5 singleton-lignende pr\u00e6cision for disse v\u00e6rdier. Ved fint spredte, kontinuerlige data \u00f8ger jeg antallet af buckets trinvist, indtil EXPLAIN viser den \u00f8nskede <strong>Selektivitet<\/strong> afspejler.<\/p>\n<p>Vigtigt: Histogrammer er <strong>i \u00e9n kolonne<\/strong>. Afh\u00e6ngigheder mellem kolonner (f.eks. status og country) kan ikke afbildes direkte. I s\u00e5danne tilf\u00e6lde kan det v\u00e6re en hj\u00e6lp at oprette et histogram for den mest selektive kolonne og tilpasse sammenk\u00e6dningsr\u00e6kkef\u00f8lgen i overensstemmelse hermed.<\/p>\n\n<h2>S\u00e5dan v\u00e6lger du de rigtige spande<\/h2>\n<p>MySQL bruger som standard 100 <strong>Spande<\/strong>, men tillader 1 til 1024 via WITH N BUCKETS. Flere buckets \u00f8ger opl\u00f8sningen, men medf\u00f8rer ogs\u00e5 en stigning i metadata og analyseindsatsen. Jeg starter som regel konservativt, m\u00e5ler effekten p\u00e5 EXPLAIN og \u00f8ger antallet gradvist, hvis planen fortsat virker uhensigtsm\u00e6ssig. Ved st\u00e6rkt koncentrerede v\u00e6rdier (f.eks. 90 % i \u00e9n status) er f\u00e5 buckets ofte tilstr\u00e6kkelige; ved spredte priser eller tidsstempler er det en fordel med flere buckets. M\u00e5let er en fornuftig <strong>Granularitet<\/strong>, hvilket har reduceret fejlvurderingerne m\u00e6rkbart uden at \u00f8ge den administrative byrde un\u00f8digt.<\/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\/08\/mysql_histogramm_meeting_8123.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Praksis: Workflow med ANALYZE TABLE<\/h2>\n<p>Jeg f\u00f8lger en klar <strong>Arbejdsgang<\/strong>: F\u00f8rst identificerer jeg kolonner, der ofte forekommer i WHERE- eller JOIN-betingelser og som tydeligvis har sk\u00e6ve fordelinger. Derefter genererer jeg et histogram med ANALYZE TABLE tbl UPDATE HISTOGRAM ON col WITH N BUCKETS; og kontrollerer det via INFORMATION_SCHEMA.COLUMN_STATISTICS. Efter dataflytninger opdaterer jeg igen med ANALYZE TABLE. Hvis en statistik ikke passer, fjerner jeg den med ANALYZE TABLE tbl DROP HISTOGRAM ON col;. For at vurdere planens effekt l\u00e6ser jeg <a href=\"https:\/\/webhosting.de\/da\/mysql-explain-analyze-fortolkning-af-foresporgsler-optimering-af-foresporgsler\/\">Fortolk EXPLAIN ANALYZE<\/a> og sammenligning af sk\u00f8n med de faktiske tal <strong>Linjer<\/strong> fra.<\/p>\n\n<h2>Konkrete ordrer og kontrol<\/h2>\n<p>Jeg arbejder p\u00e5 en reproducerbar m\u00e5de med f\u00e5, klare trin og tjekker de genererede JSON-statistikker.<\/p>\n<pre><code>-- Oprette histogrammer p\u00e5 enkelte kolonner\nANALYZE TABLE orders UPDATE HISTOGRAM ON status WITH 32 BUCKETS;\nANALYZE TABLE orders UPDATE HISTOGRAM ON created_at WITH 128 BUCKETS;\n\n-- Flere kolonner i \u00e9n k\u00f8rsel med samme antal buckets\nANALYZE TABLE orders UPDATE HISTOGRAM ON status, payment_method WITH 64 BUCKETS;\n\n-- M\u00e5lrettet sletning af histogrammer\nANALYZE TABLE orders DROP HISTOGRAM ON status;\n<\/code><\/pre>\n<pre><code>-- Visuel gennemgang af statistikken\nSELECT\n  SCHEMA_NAME, TABLE_NAME, COLUMN_NAME,\n  JSON_PRETTY(HISTOGRAM) AS histogram\nFROM INFORMATION_SCHEMA.COLUMN_STATISTICS\nWHERE SCHEMA_NAME = DATABASE()\n  AND TABLE_NAME = 'orders'\n  AND COLUMN_NAME IN ('status','created_at');\n<\/code><\/pre>\n<p>Jeg vurderer effekten direkte med EXPLAIN ANALYZE:<\/p>\n<pre><code>EXPLAIN ANALYZE\nSELECT *\nFROM orders\nWHERE status = 'canceled'\n  AND created_at &gt;= NOW() - INTERVAL 7 DAY;\n<\/code><\/pre>\n<p>Bliver sk\u00f8nnet bedre <strong>r\u00e6kker<\/strong> Hvis der er en m\u00e6rkbar forskel, og planen f.eks. skifter fra en fuld scanning til en indeks-range-scanning eller \u00e6ndrer r\u00e6kkef\u00f8lgen af sammenk\u00e6dninger, har foranstaltningen v\u00e6ret en succes. Hvis afvigelsen fortsat er stor, \u00f8ger eller reducerer jeg antallet af buckets og sammenligner igen.<\/p>\n\n<h2>Eksempel: Ordrestatus og sj\u00e6ldne v\u00e6rdier<\/h2>\n<p>I en ordretabel er status \u201ecompleted\u201c ofte den mest udbredte, mens \u201epending\u201c forekommer med middelhyppighed og \u201ecanceled\u201c er meget sj\u00e6lden; denne <strong>Ubalance<\/strong> f\u00f8rer uden et histogram let til forkerte selektiviteter. Hvis en API foresp\u00f8rger p\u00e5 \u201ecanceled\u201c, kan optimeringsmodulet fejlagtigt v\u00e6lge en fuld tabelscanning, selvom en pr\u00e6cis indeksadgang er tilstr\u00e6kkelig. Med et singleton-histogram genkender MySQL, at \u201ecanceled\u201c kun udg\u00f8r en ubetydelig andel, og skifter til en indeks-range-scan eller optimerer sammenf\u00f8jningsr\u00e6kkef\u00f8lgen. P\u00e5 den m\u00e5de falder ventetiden, og jeg beh\u00f8ver ikke et ekstra indeks for hver <strong>Variant<\/strong> i et filter. I dashboards med strenge SLO\u2019er giver denne justering ofte m\u00e6rkbare fordele i reaktionstiden.<\/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\/08\/mysql-histograms-server-room-2973.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Tidsserier og tidsstempler<\/h2>\n<p>N\u00e5r det g\u00e6lder tidsserier, er der mange <strong>Adgange<\/strong> baseret p\u00e5 nye data; \u00e6ldre tidsvinduer forbliver som regel uaktiverede. Et Equi-Height-histogram baseret p\u00e5 created_at eller updated_at skelner mellem tidsintervaller med h\u00f8j aktivitet og sj\u00e6ldent anvendte tidsintervaller. Optimizeren vurderer derefter korrekt, om en range-scan er hensigtsm\u00e6ssig, eller om en table-scan f\u00f8rer hurtigere til m\u00e5let. Is\u00e6r ved partielle tidsfiltre p\u00e5 store tabeller bem\u00e6rker jeg tydelige \u00e6ndringer i udf\u00f8relsesplanen og lavere I\/O-omkostninger. Jeg anser <strong>Statistik<\/strong> her opdateres oftere, fordi fokus flytter sig i takt med den daglige drift.<\/p>\n\n<h2>Partitioner, datatyper og sorteringsregler<\/h2>\n<p>P\u00e5 partitionerede tabeller unders\u00f8ger jeg datafordelingen <strong>p\u00e5 alle partitioner<\/strong>. Store udsving (f.eks. p\u00e5 m\u00e5nedsbasis) kan udj\u00e6vne globale histogrammer. Hvis enkelte partitioner er ekstremt selektive eller ekstremt brede, tester jeg desuden med partition-pruning-filtre i WHERE-s\u00e6tningen, om planens kvalitet alligevel er tilfredsstillende. Generelt s\u00f8rger jeg for at formulere filtre p\u00e5 en s\u00e5dan m\u00e5de, at MySQL tidligt <strong>udelukke<\/strong> kan.<\/p>\n<p>Histogrammer fungerer bedst med skal\u00e6re, sammenlignelige datatyper (tal, dato-\/tidsv\u00e6rdier, VARCHAR\/CHAR med passende sorteringsregler). Ved <strong>LOB-\/JSON-data<\/strong> s\u00e5 satser jeg hellere p\u00e5 <em>Genererede kolonner<\/em> med udtrukne, typebestemte v\u00e6rdier og tilf\u00f8j om n\u00f8dvendigt histogrammer eller indekser. For strenge bestemmer <strong>Sortering<\/strong> sammenligningslogikken; afh\u00e6ngigt af sorteringsordenen kan v\u00e6rdier v\u00e6re identiske (f.eks. store og sm\u00e5 bogstaver). Jeg s\u00f8rger for, at sorteringsordenen er i overensstemmelse med foresp\u00f8rgslerne for at opn\u00e5 realistiske selektiviteter.<\/p>\n\n<h2>Gr\u00e6nser og fejltrin<\/h2>\n<p>Histogrammer viser is\u00e6r enkelte kolonner med <strong>Konstanter<\/strong> Godt; de kan dog kun i begr\u00e6nset omfang afspejle afh\u00e6ngigheder mellem flere kolonner. Ved st\u00e6rkt korrelerede kolonner eller dynamiske parametre (f.eks. udfyldt af applikationen) st\u00f8der de p\u00e5 begr\u00e6nsninger. Booleske felter eller kolonner med en n\u00e6sten j\u00e6vn fordeling drager sj\u00e6ldent fordel af yderligere statistik. For mange kategorier og overdreven vedligeholdelse kan til geng\u00e6ld \u00f8ge administrations- og analysetiden. Derfor bruger jeg histogrammer m\u00e5lrettet og kontrollerer regelm\u00e6ssigt <strong>Effekt<\/strong> p\u00e5 virkelige udf\u00f8relser.<\/p>\n\n<h2>Kontrol og opdatering af Optimizer<\/h2>\n<p>Jeg tjekker den <strong>Brug<\/strong> fra histogrammer via ANALYZE TABLE og relevante optimeringsindstillinger, s\u00e5 planl\u00e6ggeren kan udnytte statistikkerne p\u00e5 en fornuftig m\u00e5de. I travle systemer planl\u00e6gger jeg opdateringen i rolige tidsvinduer eller i batcher efter st\u00f8rre indl\u00e6sninger. F\u00f8r og efter sammenligner jeg EXPLAIN- og EXPLAIN ANALYZE-udskrifter for at vurdere \u00e6ndrede sammenk\u00e6dningsr\u00e6kkef\u00f8lger, filtreringstrin og omkostningsmodeller. Ved negative effekter reagerer jeg straks og ruller en statistik tilbage. For yderligere styring af <a href=\"https:\/\/webhosting.de\/da\/mysql-optimizer-query-hosting-optimering-serverboost\/\">Optimeringsindstillinger<\/a> s\u00f8rger jeg for, at afh\u00e6ngigheder med andre statistikker ikke ubem\u00e6rket f\u00f8rer til forkerte <strong>Antagelser<\/strong> producerer.<\/p>\n\n<h2>Overv\u00e5gning, beskyttelse mod tilbagegang og playbook<\/h2>\n<p>Jeg bygger mig en letv\u00e6gts <strong>Playbook<\/strong> til produktionsdrift:<\/p>\n<ul>\n  <li>Fastl\u00e6gge baseline: F\u00f8r \u00e6ndringerne foretages, skal man k\u00f8re EXPLAIN ANALYZE og notere k\u00f8retid, \u201erows examined\u201c og handler-t\u00e6lleren.<\/li>\n  <li>Opret\/rediger histogram: m\u00e5lrettet mod filterkolonnerne, konservative kategorier.<\/li>\n  <li>M\u00e5l straks derefter: Plan, estimerede kontra faktiske linjer; en afvigelse p\u00e5 mere end 10 gange er for mig et advarselssignal.<\/li>\n  <li>Finjustering: Flyt buckets op\/ned; juster om n\u00f8dvendigt filterr\u00e6kkef\u00f8lgen i foresp\u00f8rgslen.<\/li>\n  <li>V\u00e6r klar til at foretage en rollback: DROP HISTOGRAM, hvis forsinkelserne stiger.<\/li>\n  <li>Automatisering: K\u00f8r ANALYZE i vedligeholdelsesvinduer efter ETL-indl\u00e6sninger eller st\u00f8rre DML-b\u00f8lger.<\/li>\n<\/ul>\n<p>Til \u00e5rsagsanalysen bruger jeg <strong>Optimizer-traces<\/strong> og EXPLAIN ANALYZE for at se, om planl\u00e6ggeren p\u00e5 baggrund af histogrammerne tr\u00e6kker den rigtige selektive tabel \u201efrem\u201c. Til A\/B-tests fastl\u00e6gger jeg som test den r\u00e6kkef\u00f8lge, hvori sammenf\u00f8jningerne skal foreg\u00e5 (STRAIGHT_JOIN), eller jeg tvinger\/forhindrer brugen af enkelte indekser for at kunne vurdere statistikkens effekt isoleret.<\/p>\n<p>Organisatorisk set har en kort <strong>\u00c6ndringslog<\/strong> pr. tabel: kolonne, antal buckets, tidspunkt, m\u00e5lev\u00e6rdier f\u00f8r\/efter. Det g\u00f8r det lettere at foretage senere korrektioner og forhindrer uklare interaktioner.<\/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\/08\/mysql_histogram_techoffice_4829.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Operationelle aspekter: Sp\u00e6rring, omkostninger, portabilitet<\/h2>\n<p>ANALYZE TABLE udf\u00f8rer en <strong>Metadatasperre<\/strong> i tabellen, men blokerer ikke de s\u00e6dvanlige l\u00e6se-\/skriveoperationer permanent. Ved meget store tabeller afs\u00e6tter jeg tilstr\u00e6kkelig tid; generering af histogrammer foreg\u00e5r ved hj\u00e6lp af stikpr\u00f8ver og er begr\u00e6nset af hukommelsen (n\u00f8gleord: intern arbejdshukommelse til beregningen). Selve statistikkens pladsbehov forbliver moderat: Et par dusin til nogle f\u00e5 hundrede kilobyte pr. kolonne med 100\u2013256 buckets er et realistisk vejledende tal. Samlet set regner jeg alligevel med det, for mange kolonner gange mange tabeller giver <strong>synlige metadata<\/strong>.<\/p>\n<p>Med <strong>Logiske dumps<\/strong> (mysqldump) overf\u00f8res histogrammer ikke som data; efter en gendannelse opretter jeg dem m\u00e5lrettet p\u00e5 ny. Ved en in-place-opgradering bevares de. P\u00e5 brugersiden har jeg brug for tilstr\u00e6kkelige rettigheder til at udf\u00f8re ANALYZE TABLE p\u00e5 de p\u00e5g\u00e6ldende objekter; i strengt regulerede milj\u00f8er integrerer jeg vedligeholdelsen i vedligeholdelsespipelines.<\/p>\n\n<h2>Hvorn\u00e5r histogrammer ikke er til nogen nytte<\/h2>\n<p>Jeg sparer mig selv for <strong>Histogrammer<\/strong> p\u00e5 kolonner, der indeholder meget f\u00e5 v\u00e6rdier og alligevel kan estimeres godt. Ogs\u00e5 der, hvor et godt indeks allerede d\u00e6kker minimale s\u00e6t af resultater, giver et histogram sj\u00e6ldent yderligere gevinst. J\u00e6vne fordelinger kr\u00e6ver ikke omfattende detaljeringsgrad. I meget dynamiske, skriveintensive systemer kan vedligeholdelsen skabe un\u00f8dvendig belastning, hvis jeg udf\u00f8rer den for ofte. I s\u00e5danne situationer anvender jeg <strong>Energi<\/strong> hellere i indeksstrategier, query-design og caching.<\/p>\n\n<h2>Oversigt i tabelform<\/h2>\n<p>Jeg bruger f\u00f8lgende <strong>Oversigt<\/strong> til hurtige beslutninger: Hvilken histogramtype passer bedst, hvordan indstiller jeg buckets, og hvilke omkostninger er der forbundet med det. Tabellen fungerer som en huskeliste ved gennemgang af problematiske foresp\u00f8rgsler. Jeg opdaterer den p\u00e5 baggrund af erfaringer fra EXPLAIN ANALYZE og produktionsmetrikker. Her tager jeg h\u00f8jde for, at datadistributioner \u00e6ndrer sig, og at historiske antagelser bliver for\u00e6ldede. Det afg\u00f8rende er stadig at <strong>Planens kvalitet<\/strong> at bekr\u00e6fte ved hj\u00e6lp af reelle m\u00e5linger.<\/p>\n<table>\n  <thead>\n    <tr>\n      <th>Aspekt<\/th>\n      <th>Anbefaling<\/th>\n      <th>Fordel<\/th>\n      <th>kompromis<\/th>\n      <th>Eksempel<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>Type<\/td>\n      <td>Singleton ved f\u00e5, dominerende v\u00e6rdier<\/td>\n      <td>Pr\u00e6cise rammeprocenter for almindelige kategorier<\/td>\n      <td>Ikke s\u00e6rlig nyttigt ved sammenh\u00e6ngende omr\u00e5der<\/td>\n      <td>ordrestatus<\/td>\n    <\/tr>\n    <tr>\n      <td>Type<\/td>\n      <td>Equi-Height ved sk\u00e6ve, kontinuerlige data<\/td>\n      <td>Bedre sk\u00f8n langs v\u00e6rdiomr\u00e5det<\/td>\n      <td>Flere metadata ved mange buckets<\/td>\n      <td>oprettet_dato, pris<\/td>\n    <\/tr>\n    <tr>\n      <td>Spande<\/td>\n      <td>Start med 100, og juster derefter<\/td>\n      <td>Afbalanceret opl\u00f8sning<\/td>\n      <td>St\u00f8rre analyse- og lagerbelastning ved 512\u20131024<\/td>\n      <td>MED 100 SPANDE<\/td>\n    <\/tr>\n    <tr>\n      <td>Pleje<\/td>\n      <td>Efter st\u00f8rre \u00e6ndringer i dataene: ANALYZE<\/td>\n      <td>Aktuelle selektiviteter<\/td>\n      <td>Planl\u00e6gge vedligeholdelsesvindue<\/td>\n      <td>ANALYZE TABLE \u2026 UPDATE HISTOGRAM<\/td>\n    <\/tr>\n    <tr>\n      <td>Kontrol<\/td>\n      <td>Kontroller via COLUMN_STATISTICS<\/td>\n      <td>Gennemsigtighed og revision<\/td>\n      <td>JSON-fortolkning p\u00e5kr\u00e6vet<\/td>\n      <td>INFORMATION_SCHEMA.COLUMN_STATISTICS<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h2>Indpasning i det samlede billede af tuning<\/h2>\n<p>Jeg behandler <strong>Histogrammer<\/strong> som en byggesten ved siden af indekser, foresp\u00f8rgselsdesign, caching og hardwareparametre. Ofte \u00e6ndrer et godt histogram r\u00e6kkef\u00f8lgen af sammenf\u00f8jninger, reducerer I\/O og sikrer konstante svartider. Alligevel kan det ikke erstatte velgennemt\u00e6nkte indeksstrategier og et effektivt skema. Den, der ser n\u00e6rmere p\u00e5 planl\u00e6gningsbeslutninger, drager fordel af <a href=\"https:\/\/webhosting.de\/da\/planer-for-udforelse-af-databaseforesporgsler-hosting-optimering-performance-indsigt\/\">At forst\u00e5 udf\u00f8relsesplaner<\/a> og sammenligner omkostningsmodeller med de faktiske l\u00f8betider. Jeg kontrollerer regelm\u00e6ssigt, om <strong>Arbejdsbyrder<\/strong> om de stadig stemmer overens med statistikkerne, eller om der er behov for justeringer.<\/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\/08\/mysql-queryplanung-8216.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Avancerede sammenf\u00f8jningsscenarier<\/h2>\n<p>Histogrammer er is\u00e6r nyttige, n\u00e5r der er flere tabeller med filtre involveret. Eksempel:<\/p>\n<pre><code>SELECT o.id, o.amount\nFROM users u\nJOIN orders o ON o.user_id = u.id\nWHERE u.country = 'DE'\n  AND o.status = 'canceled'\n  AND o.created_at &gt;= NOW() - INTERVAL 30 DAY;\n<\/code><\/pre>\n<p>Uden histogrammer kan optimeringsv\u00e6rkt\u00f8jet i visse tilf\u00e6lde undervurdere selektiviteten af o.status=\u2019canceled\u2018 eller overvurdere andelen af tyske brugere. Med et histogram p\u00e5 <em>u.land<\/em> og <em>o.status<\/em> (eventuelt ogs\u00e5 p\u00e5 <em>o.created_at<\/em>) indser planl\u00e6ggeren som regel, at kombinationen er ekstremt selektiv. I praksis ser jeg s\u00e5, at MySQL f\u00f8rst bestemmer den mindre delm\u00e6ngde (f.eks. via indeks p\u00e5 users(country) eller orders(status, created_at)) og f\u00f8rst derefter udf\u00f8rer sammenf\u00f8jningen \u2013 i stedet for at scanne den store tabel. Det sparer I\/O, bufferplads og CPU-ressourcer og stabiliserer latenstiden, selv under belastning.<\/p>\n<p>Fordi histogrammer kun <strong>i \u00e9n kolonne<\/strong> er, forbliver indeksstrategier vigtige: Et sammensat indeks p\u00e5 (status, created_at) kan yderligere fremskynde range-scanningen. Histogrammet sikrer her f\u00f8rst og fremmest, at optimeringsmodulet denne <em>Strategi<\/em> overhovedet anser for at v\u00e6re billig.<\/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\/08\/mysql_histogram_desk_4721.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Resum\u00e9 til brug i praksis<\/h2>\n<p>Jeg s\u00e6tter <strong>MySQL<\/strong>-Histogrammer, n\u00e5r optimeringsmodulet tager fejl med standardstatistikker, og sk\u00e6ve fordelinger genererer forkerte planer. Med ANALYZE TABLE opretter, opdaterer og fjerner jeg m\u00e5lrettet statistikker p\u00e5 de kolonner, der dominerer i filtre og sammenk\u00e6dninger. Jeg v\u00e6lger mellem Singleton og Equi-Height ud fra dataene, og jeg kalibrerer antallet af buckets ved hj\u00e6lp af m\u00e5linger. Med EXPLAIN ANALYZE kontrollerer jeg, om sammenkoblingsr\u00e6kkef\u00f8lger, filterpositioner og scanninger \u00e6ndres som \u00f8nsket. P\u00e5 den m\u00e5de opn\u00e5r jeg med f\u00e5 <strong>Overhead<\/strong> M\u00e6rkbart hurtigere foresp\u00f8rgsler \u2013 ofte uden yderligere indekser.<\/p>","protected":false},"excerpt":{"rendered":"<p>Find ud af, hvordan MySQL-histogrammer forsyner optimeringsmodulet med pr\u00e6cise optimeringsstatistikker, muligg\u00f8r bedre foresp\u00f8rgselsplaner og markant forbedrer din SQL-tuning uden yderligere indekser.<\/p>","protected":false},"author":1,"featured_media":21011,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[781],"tags":[],"class_list":["post-21018","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":"102","_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":"MySQL Histograms","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":"21011","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/21018","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=21018"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/21018\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media\/21011"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media?parent=21018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/categories?post=21018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/tags?post=21018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}