{"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-histogrammen-betere-queryplannen-zonder-index-optimizer","status":"publish","type":"post","link":"https:\/\/webhosting.de\/nl\/mysql-histograms-bessere-query-plaene-ohne-index-optimizer\/","title":{"rendered":"MySQL-histogrammen \u2013 Betere queryplannen zonder index"},"content":{"rendered":"<p><strong>MySQL-histogrammen<\/strong> voorzien de optimizer van echte distributiegegevens, zodat hij de selectiviteit correct kan inschatten en snellere queryplannen kan genereren \u2013 vaak zelfs zonder extra index. Ik laat zien hoe ik in MySQL 8+ histogrammen opzet met ANALYZE TABLE, deze controleer en gebruik voor betere beslissingen bij joins, filters en scans.<\/p>\n\n<h2>Centrale punten<\/h2>\n<p><strong>Korte focus<\/strong>: De volgende punten geven aan waar ik bij het gebruik van histogrammen extra op let.<\/p>\n<ul>\n  <li><strong>Selectiviteit<\/strong> in plaats van een onderbuikgevoel: realistischere schattingen van de kardinaliteit<\/li>\n  <li><strong>Zonder index<\/strong> sneller: betere keuze van het plan bij scheve verdelingen<\/li>\n  <li><strong>Typen<\/strong> begrijpen: Singleton versus Equi-Height doelgericht inzetten<\/li>\n  <li><strong>Emmers<\/strong> belasting: afweging tussen afschrijving en kosten voor metadata<\/li>\n  <li><strong>Zorg<\/strong> In het oog: bijwerken, controleren, indien nodig verwijderen<\/li>\n<\/ul>\n\n<h2>Waarom histogrammen zonder index effect sorteren<\/h2>\n<p>Ik gebruik <strong>Histogrammen<\/strong>, omdat de optimizer anders vaak uitgaat van een gelijkmatige verdeling en daardoor slechte plannen kiest. Een histogram geeft de <strong>Verdeling van waarden<\/strong> begint bij een kolom en levert daarmee realistische selectiviteitsschattingen voor predikaten zoals =, &gt;, BETWEEN, IN of IS NULL. De optimizer beslist vervolgens of een index-range-scan, een table-scan of een join-strategie met nested loops voordeliger is. Als een voorwaarde bijvoorbeeld slechts 0,1 % van de rijen treft, geef ik de voorkeur aan een gerichte toegang in plaats van een brede scan. Als een filter daarentegen bijna alle rijen selecteert, zie ik af van dure indextoegangen die geen voordeel opleveren en verhoog ik zo de <strong>Effici\u00ebntie<\/strong> elk 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>Soorten histogrammen in MySQL 8.0<\/h2>\n<p>Ik maak onderscheid tussen twee <strong>Typen<\/strong>: Singleton en Equi-Height. Singleton-histogrammen groeperen veelvoorkomende afzonderlijke waarden in aparte buckets \u2013 ideaal voor kolommen met een klein aantal dominante categorie\u00ebn zoals \u201eactief\u201c, \u201einactief\u201c of \u201egearchiveerd\u201c. Equi-Height-histogrammen verdelen het waardenbereik zodanig dat elke bucket ongeveer evenveel <strong>Lijnen<\/strong> bevat; dit is geschikt voor continue of onregelmatige verdelingen, zoals prijzen, tijdstempels of ID-reeksen met \u201egaten\u201c. Beide varianten leveren de optimizer nauwkeurigere trefpercentages voor filters op. Ik kies het type altijd op basis van de eigenschappen van de gegevens, niet op basis van persoonlijke voorkeur.<\/p>\n\n<h2>Technische basisprincipes: het selecteren van typen in MySQL beheren<\/h2>\n<p>MySQL bepaalt de concrete <strong>Histogramvariant<\/strong> automatisch op basis van de gegevensverdeling. In de praktijk betekent dit: als het aantal verschillende waarden (NDV) klein genoeg is in verhouding tot het aantal buckets, ontstaat er in feite een singleton-histogram; anders wordt er een equi-height-histogram gegenereerd. Ik \u201ekies\u201c daarom het type <em>indirect<\/em>, door de juiste kolom en een passend aantal buckets te kiezen. Voor kolommen met zeer weinig, maar sterk dominante categorie\u00ebn stel ik bewust weinig buckets in om een singleton-achtige precisie voor deze waarden te behouden. Bij fijn gespreide, continue gegevens verhoog ik het aantal buckets stapsgewijs totdat EXPLAIN de gewenste <strong>Selectiviteit<\/strong> weerspiegelt.<\/p>\n<p>Belangrijk: histogrammen zijn <strong>in \u00e9\u00e9n kolom<\/strong>. Afhankelijkheden tussen kolommen (bijvoorbeeld status en country) kunt u niet rechtstreeks weergeven. In dergelijke gevallen helpt het om de meest selectieve kolom van een histogram te voorzien en de volgorde van de joins daarop af te stemmen.<\/p>\n\n<h2>De juiste emmers kiezen<\/h2>\n<p>MySQL gebruikt standaard 100 <strong>Emmers<\/strong>, maar staat 1 tot 1024 toe via WITH N BUCKETS. Meer buckets verhogen de resolutie, maar zorgen ook voor meer metadata en meer analysewerk. Ik begin meestal voorzichtig, meet het effect op EXPLAIN en verhoog het aantal stapsgewijs als het plan nog steeds niet geschikt lijkt. Bij sterk geconcentreerde waarden (bijv. 90 % in \u00e9\u00e9n status) volstaan vaak weinig buckets; bij fijn verspreide prijzen of tijdstempels loont het om meer buckets te gebruiken. Het doel is een zinvolle <strong>Granulariteit<\/strong>, waardoor het aantal verkeerde inschattingen aanzienlijk is verminderd, zonder dat de administratieve lasten onnodig toenemen.<\/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>Praktijk: Workflow met ANALYZE TABLE<\/h2>\n<p>Ik volg een duidelijke <strong>Werkstroom<\/strong>: Eerst zoek ik kolommen die vaak in WHERE- of JOIN-voorwaarden voorkomen en die duidelijk scheve verdelingen vertonen. Vervolgens genereer ik een histogram met ANALYZE TABLE tbl UPDATE HISTOGRAM ON col WITH N BUCKETS; en controleer ik dit via INFORMATION_SCHEMA.COLUMN_STATISTICS. Na gegevensverplaatsingen werk ik de statistieken opnieuw bij met ANALYZE TABLE. Als een statistiek niet klopt, verwijder ik deze met ANALYZE TABLE tbl DROP HISTOGRAM ON col;. Om de effectiviteit van het uitvoeringsplan te beoordelen, bekijk ik <a href=\"https:\/\/webhosting.de\/nl\/mysql-explain-analyze-querys-interpreteren-query-optimalisatie\/\">EXPLAIN ANALYZE interpreteren<\/a> en dezelfde ramingen vergeleken met de werkelijke cijfers <strong>Lijnen<\/strong> van.<\/p>\n\n<h2>Concrete opdrachten en controle<\/h2>\n<p>Ik werk op een reproduceerbare manier met een klein aantal duidelijke stappen en controleer de gegenereerde JSON-statistieken.<\/p>\n<pre><code>-- Histogrammen aanmaken voor afzonderlijke kolommen\nANALYZE TABLE orders UPDATE HISTOGRAM ON status WITH 32 BUCKETS;\nANALYZE TABLE orders UPDATE HISTOGRAM ON created_at WITH 128 BUCKETS;\n\n-- Meerdere kolommen in \u00e9\u00e9n bewerking met hetzelfde aantal buckets\nANALYZE TABLE orders UPDATE HISTOGRAM ON status, payment_method WITH 64 BUCKETS;\n\n-- Histogrammen gericht verwijderen\nANALYZE TABLE orders DROP HISTOGRAM ON status;\n<\/code><\/pre>\n<pre><code>-- Visuele controle van de statistieken\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>Ik evalueer het effect direct met 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>Wordt de schatting beter? <strong>rijen<\/strong> Als er een merkbaar verschil is en het plan bijvoorbeeld overschakelt van een volledige scan naar een index-range-scan of de volgorde van de joins wijzigt, is de maatregel geslaagd. Blijft de afwijking groot, dan verhoog of verlaag ik het aantal buckets en vergelijk ik opnieuw.<\/p>\n\n<h2>Voorbeeld: orderstatus en ongebruikelijke waarden<\/h2>\n<p>In een tabel met bestellingen komt de status \u201ecompleted\u201c vaak voor, terwijl \u201epending\u201c redelijk vaak voorkomt en \u201ecanceled\u201c zeer zelden; deze <strong>onevenwicht<\/strong> leidt zonder histogram gemakkelijk tot onjuiste selectiviteiten. Als een API naar \u201ecanceled\u201c zoekt, kan de optimizer ten onrechte kiezen voor een volledige tabelscan, terwijl een beperkte indextoegang volstaat. Met een singleton-histogram herkent MySQL dat \u201ecanceled\u201c slechts een minuscuul deel uitmaakt en schakelt het over op een index-range-scan of optimaliseert het de volgorde van de joins. Zo daalt de latentie en heb ik geen extra index nodig voor elke <strong>Variant<\/strong> van een filter. In dashboards met strenge SLO\u2019s levert deze aanpassing vaak merkbare voordelen op wat betreft de reactietijd.<\/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>Tijdreeksen en tijdstempels<\/h2>\n<p>Bij tijdreeksen zijn er veel <strong>Toegang tot<\/strong> op basis van recente gegevens; oudere tijdsvensters blijven meestal ongebruikt. Een Equi-Height-histogram op `created_at` of `updated_at` maakt een onderscheid tussen drukbezochte tijdsperioden en zelden gebruikte. De optimizer schat vervolgens correct in of een range-scan zinvol is of dat een table-scan sneller tot het gewenste resultaat leidt. Vooral bij gedeeltelijke tijdsfilters op grote tabellen zie ik duidelijke wijzigingen in de uitvoeringsplan en lagere I\/O-kosten. Ik beschouw de <strong>Statistieken<\/strong> hier vaker bijgewerkt, omdat de focus verschuift naar de dagelijkse gang van zaken.<\/p>\n\n<h2>Partities, gegevenstypen en collaties<\/h2>\n<p>Ik bekijk de gegevensverdeling in gepartitioneerde tabellen <strong>over alle partities<\/strong>. Grote verschillen (bijvoorbeeld per maand) kunnen globale histogrammen afvlakken. Als afzonderlijke partities extreem selectief of extreem breed zijn, test ik bovendien met \u2018partition pruning\u2019-filters in de WHERE-clausule of de plankwaliteit toch nog in orde is. Over het algemeen let ik erop dat ik filters zo formuleer dat MySQL partities vroeg <strong>uitsluiten<\/strong> kan.<\/p>\n<p>Histogrammen werken het beste bij scalaire, vergelijkbare gegevenstypen (getallen, datum-\/tijdwaarden, VARCHAR\/CHAR met de juiste collatie). Bij <strong>LOB-\/JSON-gegevens<\/strong> ik geef de voorkeur aan <em>Gegenereerde kolommen<\/em> met ge\u00ebxtraheerde, getypeerde waarden en voorzie deze indien nodig van histogrammen of indexen. Bij strings bepaalt de <strong>Verzameling<\/strong> de vergelijkingslogica; afhankelijk van de collatie kunnen waarden overeenkomen (bijv. hoofdletters\/kleine letters). Ik houd de collatie consistent met de query\u2019s om realistische selectiviteiten te verkrijgen.<\/p>\n\n<h2>Grenzen en misstappen<\/h2>\n<p>Histogrammen geven vooral een beeld van afzonderlijke kolommen met <strong>Constanten<\/strong> Goed; ze geven afhankelijkheid tussen meerdere kolommen slechts in beperkte mate weer. Bij sterk gecorreleerde kolommen of dynamische parameters (bijvoorbeeld door de gebruiker ingevuld) stoten ze op hun grenzen. Booleaanse velden of kolommen met een vrijwel gelijkmatige verdeling hebben zelden baat bij aanvullende statistieken. Te veel buckets en buitensporig onderhoud kunnen op hun beurt de beheer- en analysetijd verlengen. Daarom gebruik ik histogrammen doelgericht en controleer ik regelmatig de <strong>Effect<\/strong> op daadwerkelijke uitvoeringen.<\/p>\n\n<h2>Controle en update van de Optimizer<\/h2>\n<p>Ik controleer de <strong>Gebruik<\/strong> van histogrammen via ANALYZE TABLE en relevante optimizer-opties, zodat de planner de statistieken op een zinvolle manier kan gebruiken. In drukke systemen plan ik de update in rustige tijdsvensters of in batches na grotere loads. Voor en na vergelijk ik de uitvoer van EXPLAIN en EXPLAIN ANALYZE om gewijzigde join-volgordes, filterstappen en kostenmodellen te evalueren. Bij negatieve effecten reageer ik onmiddellijk en draai ik een statistiek terug. Voor verdere controle van de <a href=\"https:\/\/webhosting.de\/nl\/mysql-optimizer-query-hosting-optimalisatie-serverboost\/\">Optimalisatie-opties<\/a> let ik erop dat afhankelijkheden met andere statistieken niet onopgemerkt tot onjuiste <strong>Veronderstellingen<\/strong> produceren.<\/p>\n\n<h2>Monitoring, bescherming tegen regressie en draaiboek<\/h2>\n<p>Ik bouw een lichtgewicht <strong>Playbook<\/strong> voor de productieve omgeving:<\/p>\n<ul>\n  <li>Een basislijn vaststellen: v\u00f3\u00f3r het doorvoeren van wijzigingen EXPLAIN ANALYZE uitvoeren, de looptijd, het aantal \u201erows examined\u201c en de handler-teller noteren.<\/li>\n  <li>Histogram aanmaken\/wijzigen: gericht op de filterkolommen, conservatieve buckets.<\/li>\n  <li>Direct daarna meten: plan, geschatte versus werkelijke regels; een afwijking met een factor &gt;10 is voor mij een waarschuwingssignaal.<\/li>\n  <li>Fijnafstelling: buckets omhoog\/omlaag; pas indien nodig de volgorde van de filters in de query aan.<\/li>\n  <li>Zorg dat je een rollback achter de hand hebt: DROP HISTOGRAM, mochten de vertragingen toenemen.<\/li>\n  <li>Automatisering: ANALYZE na ETL-loads of grotere DML-golven tijdens onderhoudsvensters.<\/li>\n<\/ul>\n<p>Voor de oorzaakanalyse maak ik gebruik van <strong>Optimizer-traces<\/strong> en EXPLAIN ANALYZE, om te zien of de planner op basis van de histogrammen de juiste selectieve tabel \u201enaar voren\u201c haalt. Voor A\/B-tests leg ik bij wijze van test de volgorde van de joins vast (STRAIGHT_JOIN) of dwing ik het gebruik van bepaalde indexen af of verbied ik deze, om het effect van de statistiek ge\u00efsoleerd te kunnen beoordelen.<\/p>\n<p>Op organisatorisch vlak heeft een korte <strong>Veranderingslogboek<\/strong> per tabel: kolom, aantal buckets, tijdstip, meetwaarden voor en na. Dit vergemakkelijkt latere correcties en voorkomt onduidelijke interacties.<\/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>Operationele aspecten: blokkeringen, kosten, overdraagbaarheid<\/h2>\n<p>ANALYZE TABLE voert een <strong>Metadata-blokkering<\/strong> in de tabel, maar blokkeert de gebruikelijke lees- en schrijfbewerkingen niet permanent. Bij zeer grote tabellen houd ik rekening met voldoende tijd; het genereren van histogrammen werkt met steekproeven en is beperkt door het geheugen (trefwoord: intern werkgeheugen voor de berekening). De benodigde ruimte voor de statistiek zelf blijft beperkt: enkele tientallen tot een paar honderd kilobyte per kolom met 100\u2013256 buckets is een realistische richtwaarde. In totaal maak ik toch een berekening, want veel kolommen maal veel tabellen leveren <strong>zichtbare metagegevens<\/strong>.<\/p>\n<p>Op <strong>Logische dumps<\/strong> (mysqldump) worden histogrammen niet als gegevens meegenomen; na een restore maak ik ze gericht opnieuw aan. Bij een in-place-upgrade blijven ze behouden. Aan de gebruikerszijde heb ik voldoende rechten nodig voor ANALYZE TABLE op de betreffende objecten; in streng gereguleerde omgevingen integreer ik het onderhoud in onderhoudspijplijnen.<\/p>\n\n<h2>Wanneer histogrammen geen zin hebben<\/h2>\n<p>Ik sla het over <strong>Histogrammen<\/strong> voor kolommen die maar heel weinig waarden bevatten en toch al goed kunnen worden ingeschat. Ook wanneer een goede index al minimale sets met treffers dekt, levert een histogram zelden extra voordeel op. Gelijkmatige verdelingen vereisen geen uitgebreide fijnmazigheid. In zeer dynamische, schrijfintensieve systemen kan het onderhoud onnodige belasting veroorzaken als ik het te vaak start. In dergelijke situaties gebruik ik de <strong>Energie<\/strong> liever in indexstrategie\u00ebn, query-ontwerp en caching.<\/p>\n\n<h2>Spiekbriefje in tabelvorm<\/h2>\n<p>Ik gebruik het volgende <strong>Overzicht<\/strong> voor snelle beslissingen: welk type histogram is geschikt, hoe stel ik buckets in en welke kosten zijn hieraan verbonden. De tabel dient als geheugensteuntje bij het beoordelen van problematische query's. Ik werk deze bij op basis van inzichten uit EXPLAIN ANALYZE en productiemetrics. Daarbij houd ik er rekening mee dat gegevensverdelingen veranderen en historische aannames achterhaald raken. Cruciaal blijft dat de <strong>Kwaliteit van het plan<\/strong> met behulp van echte metingen te bevestigen.<\/p>\n<table>\n  <thead>\n    <tr>\n      <th>Aspect<\/th>\n      <th>Aanbeveling<\/th>\n      <th>Voordeel<\/th>\n      <th>afweging<\/th>\n      <th>Voorbeeld<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>Type<\/td>\n      <td>Singleton bij een klein aantal dominante waarden<\/td>\n      <td>Nauwkeurige trefpercentages voor veelvoorkomende categorie\u00ebn<\/td>\n      <td>Niet erg nuttig bij aaneengesloten gebieden<\/td>\n      <td>order_status<\/td>\n    <\/tr>\n    <tr>\n      <td>Type<\/td>\n      <td>Equi-Height bij scheve, continue gegevens<\/td>\n      <td>Betere schatting over het gehele waardenbereik<\/td>\n      <td>Meer metagegevens bij veel buckets<\/td>\n      <td>created_at, price<\/td>\n    <\/tr>\n    <tr>\n      <td>Emmers<\/td>\n      <td>Begin bij 100, en pas het daarna aan<\/td>\n      <td>Evenwichtige resolutie<\/td>\n      <td>Hogere analyse- en opslagbelasting bij 512\u20131024<\/td>\n      <td>MET 100 EMMERS<\/td>\n    <\/tr>\n    <tr>\n      <td>Zorg<\/td>\n      <td>Na ingrijpende wijzigingen in de gegevens: ANALYZE<\/td>\n      <td>Huidige selectiviteiten<\/td>\n      <td>Onderhoudsperiode inplannen<\/td>\n      <td>ANALYZE TABLE \u2026 UPDATE HISTOGRAM<\/td>\n    <\/tr>\n    <tr>\n      <td>Controle<\/td>\n      <td>Controleren via COLUMN_STATISTICS<\/td>\n      <td>Transparantie en audit<\/td>\n      <td>JSON-interpretatie vereist<\/td>\n      <td>INFORMATION_SCHEMA.COLUMN_STATISTICS<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h2>Plaats binnen het totale beeld van de tuning<\/h2>\n<p>Ik behandel <strong>Histogrammen<\/strong> als bouwsteen naast indexen, query-ontwerp, caching en hardwareparameters. Vaak zorgt een goed histogram ervoor dat de volgorde van de joins wordt aangepast, dat de I\/O-belasting daalt en dat de responstijden constant blijven. Toch is het geen vervanging voor een goede indexstrategie en een effici\u00ebnt schema. Wie dieper ingaat op planningsbeslissingen, profiteert van <a href=\"https:\/\/webhosting.de\/nl\/uitvoeringsplannen-van-databasequerys-hosting-inzichten-in-optimalisatieprestaties\/\">Uitvoeringsplannen begrijpen<\/a> en vergelijkt kostenmodellen met de werkelijke looptijden. Ik controleer regelmatig of de <strong>Werklasten<\/strong> nog wel overeenkomen met de statistieken of dat er aanpassingen nodig zijn.<\/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>Geavanceerde join-scenario\u2019s<\/h2>\n<p>Histogrammen zijn vooral nuttig wanneer er meerdere tabellen met filters bij betrokken zijn. Voorbeeld:<\/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>Zonder histogrammen kan de optimizer de selectiviteit van o.status=\u2019canceled\u2018 onderschatten of het aandeel Duitse gebruikers overschatten. Met een histogram op <em>u.land<\/em> en <em>o.status<\/em> (eventueel ook op <em>o.created_at<\/em>) merkt de ontwerper meestal dat de combinatie uiterst selectief is. In de praktijk zie ik dan dat MySQL eerst de kleinere subset bepaalt (bijvoorbeeld via een index op users(country) of orders(status, created_at)) en pas daarna de join uitvoert \u2013 in plaats van de grote tabel te scannen. Dat bespaart I\/O, bufferruimte en CPU-capaciteit en stabiliseert de latentie, ook onder belasting.<\/p>\n<p>Omdat histogrammen alleen <strong>in \u00e9\u00e9n kolom<\/strong> blijven indexstrategie\u00ebn belangrijk: een samengestelde index op (status, created_at) kan de range-scan verder versnellen. Het histogram zorgt er hier vooral voor dat de optimizer deze <em>Strategie<\/em> over het algemeen als voordelig beschouwt.<\/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>Samenvatting voor de praktijk<\/h2>\n<p>Ik stel <strong>MySQL<\/strong>-histogrammen als de optimizer er met standaardstatistieken naast zit en scheve verdelingen verkeerde plannen opleveren. Met ANALYZE TABLE bouw ik statistieken op, werk ik ze bij en verwijder ik ze gericht voor de kolommen die in filters en joins de boventoon voeren. De keuze tussen Singleton en Equi-Height maak ik op basis van de gegevens; het aantal buckets kalibreer ik aan de hand van metingen. Met EXPLAIN ANALYZE controleer ik of de volgorde van joins, de posities van filters en scans zoals gewenst veranderen. Zo bereik ik met weinig <strong>Overhead<\/strong> aanzienlijk snellere zoekopdrachten \u2013 vaak zonder extra indexen.<\/p>","protected":false},"excerpt":{"rendered":"<p>Ontdek hoe MySQL-histogrammen de optimizer voorzien van nauwkeurige optimizer-statistieken, betere queryplannen mogelijk maken en je SQL-tuning aanzienlijk verbeteren zonder dat je extra indexen hoeft toe te voegen.<\/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":"108","_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\/nl\/wp-json\/wp\/v2\/posts\/21018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/comments?post=21018"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/posts\/21018\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/media\/21011"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/media?parent=21018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/categories?post=21018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/tags?post=21018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}