{"id":20930,"date":"2026-08-23T15:05:18","date_gmt":"2026-08-23T13:05:18","guid":{"rendered":"https:\/\/webhosting.de\/mariadb-query-optimizer-intern-erklaert-sql-tuning-insight\/"},"modified":"2026-08-23T15:05:18","modified_gmt":"2026-08-23T13:05:18","slug":"explication-detaillee-du-fonctionnement-interne-de-loptimiseur-de-requetes-mariadb-apercu-de-loptimisation-sql","status":"publish","type":"post","link":"https:\/\/webhosting.de\/fr\/mariadb-query-optimizer-intern-erklaert-sql-tuning-insight\/","title":{"rendered":"L'optimiseur de requ\u00eates MariaDB expliqu\u00e9 en d\u00e9tail : principes fondamentaux, plans et mise en pratique"},"content":{"rendered":"<p>Je vais expliquer le <strong>Optimiseur MariaDB<\/strong> Exemples concrets : comment il \u00e9labore ses plans, estime les co\u00fbts et pourquoi il se trompe parfois. Vous apprendrez ainsi \u00e0 analyser le plan d'ex\u00e9cution SQL de mani\u00e8re cibl\u00e9e, \u00e0 utiliser les index \u00e0 bon escient et \u00e0 guider l'optimiseur en vous appuyant sur des faits plut\u00f4t que sur votre intuition.<\/p>\n\n<h2>Points centraux<\/h2>\n\n<p>Pour commencer, je vais r\u00e9sumer bri\u00e8vement les \u00e9l\u00e9ments cl\u00e9s afin que tu puisses situer les sections suivantes dans leur contexte et que tu puisses <strong>Vue d'ensemble<\/strong> tu conserves.<\/p>\n<ul>\n  <li><strong>Phases<\/strong>: L'analyse, la pr\u00e9paration, l'optimisation et l'ex\u00e9cution constituent le cycle de vie de chaque requ\u00eate.<\/li>\n  <li><strong>Mod\u00e8le de co\u00fbts<\/strong>: Les valeurs temporelles en microsecondes d\u00e9terminent le choix des index, les balayages et l'ordre des jointures.<\/li>\n  <li><strong>Statistiques<\/strong>: La cardinalit\u00e9 et l'histogramme d\u00e9terminent l'estimation de la s\u00e9lectivit\u00e9.<\/li>\n  <li><strong>Transparence<\/strong>: EXPLAIN, EXPLAIN ANALYZE et Optimizer Trace permettent d'ouvrir la \u00ab bo\u00eete noire \u00bb.<\/li>\n  <li><strong>Tuning<\/strong>: Les index, la r\u00e9\u00e9criture des requ\u00eates, la commande ANALYZE TABLE et les param\u00e8tres de co\u00fbt permettent d'acc\u00e9l\u00e9rer les op\u00e9rations.<\/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\/08\/mariaDB-query-plans-9842.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Cycle de vie d'une requ\u00eate dans MariaDB<\/h2>\n\n<p>Avant qu'un plan ne voie le jour, une requ\u00eate passe par quatre \u00e9tapes que je v\u00e9rifie syst\u00e9matiquement au quotidien afin de <strong>Causes<\/strong> pour identifier les causes de lenteur. Lors de l'analyse syntaxique, MariaDB convertit le SQL en une structure interne ; c'est \u00e0 ce stade que les erreurs de syntaxe sont d\u00e9tect\u00e9es. Lors de la phase de pr\u00e9paration, le moteur examine les tables, les colonnes et les index potentiels, et effectue des transformations simples. Vient ensuite l\u2019optimisation, au cours de laquelle des plans candidats sont calcul\u00e9s et \u00e9valu\u00e9s \u00e0 l\u2019aide d\u2019un mod\u00e8le de co\u00fbt. Lors de l\u2019ex\u00e9cution, le serveur met en \u0153uvre le plan s\u00e9lectionn\u00e9 \u00e9tape par \u00e9tape : lecture, jointure, filtrage, retour des r\u00e9sultats.<\/p>\n\n<p>Je classe clairement les erreurs d'analyse par phase, car cela permet d'\u00e9tablir plus rapidement un diagnostic et <strong>Mesures<\/strong> agir de mani\u00e8re cibl\u00e9e. La plupart du temps, les probl\u00e8mes de performances trouvent leur origine dans l\u2019optimisation : estimations erron\u00e9es, indices manquants ou ordres de jointure d\u00e9favorables. Les erreurs d\u2019analyse syntaxique sont mineures, mais la phase de pr\u00e9paration peut d\u00e9j\u00e0 comporter des subtilit\u00e9s telles que la r\u00e9solution des vues ou la transformation des sous-requ\u00eates. Lors de l\u2019ex\u00e9cution, les inefficacit\u00e9s apparaissent alors sans piti\u00e9 si un balayage complet a \u00e9t\u00e9 choisi auparavant. C\u2019est pourquoi je commence chaque analyse par un examen structur\u00e9 des quatre \u00e9tapes.<\/p>\n\n<h2>Comment l'optimiseur prend ses d\u00e9cisions en interne<\/h2>\n\n<p>MariaDB fonctionne selon un mod\u00e8le bas\u00e9 sur les co\u00fbts et \u00e9value les ex\u00e9cutions alternatives \u00e0 l'aide d'une <strong>Fonction de co\u00fbt<\/strong>. Pour chaque variante, le serveur estime le nombre de lignes lues, la s\u00e9lectivit\u00e9 des conditions WHERE\/ON, les types d\u2019acc\u00e8s tels que le balayage de table, le balayage d\u2019index et le balayage de plage, ainsi que le temps n\u00e9cessaire \u00e0 chaque op\u00e9ration. En interne, le serveur fait la distinction entre `join_preparation` et `join_optimization`. Dans `join_preparation`, sont effectu\u00e9s la r\u00e9\u00e9criture des requ\u00eates, la simplification des conditions, la transformation des sous-requ\u00eates et la r\u00e9solution des vues. La phase \u00ab join_optimization \u00bb calcule les ordres de jointure, v\u00e9rifie les index candidats via \u00ab ref_optimizer_key_uses \u00bb, estime le nombre de lignes via des balayages par plage et attribue les conditions \u00e0 des tables sp\u00e9cifiques d\u00e8s que possible.<\/p>\n\n<p>Ce m\u00e9canisme explique pourquoi un petit filtre mal plac\u00e9 peut entra\u00eener des co\u00fbts \u00e9lev\u00e9s <strong>Suivre<\/strong> . Si l'op\u00e9ration \u00ab attaching_conditions_to_tables \u00bb est effectu\u00e9e tardivement, le plan tra\u00eene inutilement un grand nombre de lignes \u00e0 travers les jointures. Si les statistiques sont obsol\u00e8tes, les estimations \u00ab rows_estimation \u00bb et \u00ab Selectivity \u00bb sont erron\u00e9es ; l'optimiseur opte alors pour des chemins d'acc\u00e8s apparemment avantageux, mais en r\u00e9alit\u00e9 lents. C\u2019est pr\u00e9cis\u00e9ment sur ces leviers que j\u2019agis : de meilleures statistiques, des pr\u00e9dicats plus clairs, des index composites soigneusement tri\u00e9s. Apr\u00e8s cela, le choix du plan s\u2019en trouve souvent sensiblement modifi\u00e9.<\/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\/MariaDBQueryOptKonferenz1234.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Mod\u00e8le de tarification \u00e0 partir de MariaDB 11.0<\/h2>\n\n<p>Les versions actuelles n'\u00e9valuent plus le travail de mani\u00e8re approximative en fonction des poids, mais \u00e0 l'aide de <strong>microsecondes<\/strong> pour des op\u00e9rations de stockage sp\u00e9cifiques. Des param\u00e8tres tels que `optimizer_disk_read_cost`, `optimizer_disk_read_ratio` et `optimizer_where_cost` permettent de rapprocher le mod\u00e8le des dur\u00e9es d'ex\u00e9cution r\u00e9elles. Ainsi, l'optimiseur compare le balayage par plage d'index (index-range-scan) au balayage complet (full scan) sur la base d'hypoth\u00e8ses de temps r\u00e9elles. LAST_QUERY_COST indique le co\u00fbt total estim\u00e9 et correspond souvent nettement mieux \u00e0 la r\u00e9alit\u00e9 qu\u2019auparavant. Pour les syst\u00e8mes traitant de grands volumes de donn\u00e9es, cette granularit\u00e9 plus fine porte imm\u00e9diatement ses fruits.<\/p>\n\n<p>Je calibre le mod\u00e8le avec pr\u00e9caution lorsque les caract\u00e9ristiques mat\u00e9rielles contredisent les hypoth\u00e8ses par d\u00e9faut et, par cons\u00e9quent, les <strong>S\u00e9lection du forfait<\/strong> fausser. Les SSD NVMe, les m\u00e9moires distribu\u00e9es ou les caches sp\u00e9cialis\u00e9s peuvent modifier sensiblement le rapport disque et les temps de lecture. De l\u00e9gers ajustements des valeurs \u00ab optimizer_costs \u00bb am\u00e8nent MariaDB \u00e0 privil\u00e9gier des chemins d'acc\u00e8s pertinents. Je documente chaque modification, puis je v\u00e9rifie EXPLAIN ANALYZE afin d\u2019en mesurer l\u2019impact. Sans mesure, l\u2019optimisation reste un coup de poker.<\/p>\n\n<h2>S\u00e9lectivit\u00e9, statistiques et histogrammes<\/h2>\n\n<p>Pour obtenir de bonnes estimations, il faut commencer par des donn\u00e9es fiables <strong>cardinalit\u00e9<\/strong> et une s\u00e9lectivit\u00e9 fiable. MariaDB conserve des statistiques sur les diff\u00e9rentes valeurs de chaque colonne et peut, en option, utiliser des histogrammes pour les distributions. Ce sont justement les donn\u00e9es h\u00e9t\u00e9rog\u00e8nes \u2013 les \u00ab hotspots \u00bb, les distributions de Zipf, les tendances saisonni\u00e8res \u2013 qui tirent profit des histogrammes. Apr\u00e8s des modifications importantes des donn\u00e9es, j\u2019ex\u00e9cute la commande ANALYZE TABLE afin que l\u2019optimisation puisse \u00e0 nouveau s\u2019appuyer sur des donn\u00e9es r\u00e9elles. Ceux qui oublient de le faire risquent de subir des analyses compl\u00e8tes qui sont objectivement erron\u00e9es.<\/p>\n\n<p>Je programme ANALYZE en tant que t\u00e2che r\u00e9guli\u00e8re, en fonction de <strong>Modifications<\/strong> en termes de volume de donn\u00e9es et sur les tables critiques. Lorsque la r\u00e9partition des colonnes est fortement asym\u00e9trique, les histogrammes permettent d'\u00e9valuer de mani\u00e8re r\u00e9aliste la s\u00e9lectivit\u00e9 des valeurs singuli\u00e8res. Cela r\u00e9duit les erreurs d\u2019estimation lors des balayages par plage et des strat\u00e9gies de fusion. Associ\u00e9e \u00e0 des index composites adapt\u00e9s, la pr\u00e9cision des r\u00e9sultats s\u2019am\u00e9liore consid\u00e9rablement. R\u00e9sultat : des dur\u00e9es d\u2019ex\u00e9cution plus courtes et moins d\u2019E\/S.<\/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\/mariadb-query-optimizer-guide-4729.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Lire les instructions EXPLAIN et les plans d'ex\u00e9cution<\/h2>\n\n<p>Pour visualiser les d\u00e9cisions, j'utilise EXPLAIN, EXPLAIN EXTENDED et <strong>FORMAT=JSON<\/strong>. Les colonnes classiques offrent un aper\u00e7u rapide : id, select_type, table, type, possible_keys, key, key_len, ref, rows et, le cas \u00e9ch\u00e9ant, filtered. Une valeur type=ALL indique un balayage complet, ce qui est rarement souhaitable. FORMAT=JSON montre en d\u00e9tail comment les conditions ont \u00e9t\u00e9 d\u00e9plac\u00e9es et quels chemins l\u2019optimiseur a \u00e9valu\u00e9s. Dans le contexte de l\u2019h\u00e9bergement, je recommande le guide sur <a href=\"https:\/\/webhosting.de\/fr\/base-de-donnees-plans-dexecution-des-requetes-hebergement-optimisation-des-performances-insights\/\">Plans d'ex\u00e9cution dans l'h\u00e9bergement<\/a>, afin de relier les informations relatives aux projets aux incidences sur les infrastructures.<\/p>\n\n<p>Pour une interpr\u00e9tation rapide, je m'aide d'un petit tableau qui r\u00e9pertorie bri\u00e8vement les valeurs typiques et qui permet ainsi <strong>Mauvaises interpr\u00e9tations<\/strong> emp\u00each\u00e9.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Champ EXPLAIN<\/th>\n      <th>Valeur typique<\/th>\n      <th>Importance dans la pratique<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>type<\/td>\n      <td>ALL, range, ref, eq_ref, const<\/td>\n      <td>Plus on va vers la droite, plus la s\u00e9lection est stricte ; \u00ab ALL \u00bb indique un balayage complet.<\/td>\n    <\/tr>\n    <tr>\n      <td>possible_keys<\/td>\n      <td>Liste des index<\/td>\n      <td>Des indices qui correspondent en th\u00e9orie ; s'il manque des candidats ici, il manque de la structure.<\/td>\n    <\/tr>\n    <tr>\n      <td>cl\u00e9<\/td>\n      <td>Nom de l'index<\/td>\n      <td>Index r\u00e9ellement utilis\u00e9 ; la valeur \u00ab vide \u00bb signifie qu'aucun index n'est utilis\u00e9.<\/td>\n    <\/tr>\n    <tr>\n      <td>lignes<\/td>\n      <td>Nombre<\/td>\n      <td>Nombre estim\u00e9 de lignes lues ; \u00e9cart important par rapport \u00e0 la r\u00e9alit\u00e9 = statistiques peu fiables.<\/td>\n    <\/tr>\n    <tr>\n      <td>filtr\u00e9<\/td>\n      <td>Pourcentage<\/td>\n      <td>Quelle quantit\u00e9 est transmise apr\u00e8s le filtre ; une faible quantit\u00e9 est souvent pr\u00e9f\u00e9rable.<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h2>Pourquoi l'optimiseur se trompe parfois<\/h2>\n\n<p>Aucun mod\u00e8le de co\u00fbts ne convient \u00e0 toutes les situations, c'est pourquoi j'apporte des corrections <strong>erreurs<\/strong> de mani\u00e8re cibl\u00e9e. Des statistiques obsol\u00e8tes entra\u00eenent des estimations erron\u00e9es du nombre de lignes et des ordres de jointure d\u00e9favorables. Des index composites mal structur\u00e9s emp\u00eachent l\u2019utilisation des index lors de filtres sur plusieurs colonnes. Les sous-requ\u00eates tr\u00e8s imbriqu\u00e9es compliquent les r\u00e9\u00e9critures efficaces et bloquent la mat\u00e9rialisation. Des filtres manquants ou trompeurs obligent le moteur \u00e0 d\u00e9placer de nombreuses lignes avant que des pr\u00e9dicats utiles ne s\u2019appliquent.<\/p>\n\n<p>Je v\u00e9rifie tout d'abord si la formulation de la requ\u00eate respecte les <strong>Index<\/strong> Ce qui fonctionne vraiment : r\u00e8gle de pr\u00e9fixe \u00e0 gauche, ordre de tri adapt\u00e9, \u00e9viter d'utiliser des fonctions sur les colonnes dans la clause WHERE. Ensuite, je v\u00e9rifie dans EXPLAIN ANALYZE si la r\u00e9alit\u00e9 corrobore l'estimation. Si ce n'est pas le cas, j'ex\u00e9cute ANALYZE TABLE et, si n\u00e9cessaire, je r\u00e9\u00e9cris la requ\u00eate. Ce n\u2019est qu\u2019en dernier recours que j\u2019utilise FORCE INDEX ou des hints, car cela peut limiter les optimisations futures.<\/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\/mariadboptimizer_2219.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Utiliser la trace de l'optimiseur de mani\u00e8re cibl\u00e9e<\/h2>\n\n<p>Si EXPLAIN ne suffit pas, j'active la trace de l'optimiseur et je surveille <strong>D\u00e9cisions<\/strong> dans le journal JSON. Je peux y voir quels plans ont \u00e9t\u00e9 envisag\u00e9s, rejet\u00e9s ou accept\u00e9s. Je comprends pourquoi une condition s'applique tardivement ou pourquoi un index n'a pas \u00e9t\u00e9 retenu. Le journal indique \u00e9galement comment les conditions ont \u00e9t\u00e9 r\u00e9organis\u00e9es. Cette vue d'ensemble permet d'affiner la compr\u00e9hension et fournit des leviers concrets pour le prochain optimisation.<\/p>\n\n<p>J'enregistre les sections pertinentes de la trace avec le hachage de la requ\u00eate et <strong>Param\u00e8tres<\/strong>\u00e9valuer. Cela me permettra ensuite de comparer l'effet de chaque modification. La documentation du serveur MariaDB et diverses pr\u00e9sentations au sein de l'\u00e9cosyst\u00e8me d\u00e9crivent ces champs en d\u00e9tail (source : documentation du serveur MariaDB sur l'optimiseur de requ\u00eates et la trace de l'optimiseur). Cet outil me permet de d\u00e9tecter plus rapidement les hypoth\u00e8ses erron\u00e9es qu\u2019en proc\u00e9dant par essais et erreurs. Je gagne surtout du temps sur les jointures complexes.<\/p>\n\n<h2>Pratique : l'optimisation des bases de donn\u00e9es, \u00e9tape par \u00e9tape<\/h2>\n\n<p>Je commence chaque optimisation par une <strong>Mesure<\/strong>. J'identifie les probl\u00e8mes gr\u00e2ce \u00e0 la surveillance et \u00e0 cela <a href=\"https:\/\/webhosting.de\/fr\/mysql-slow-query-log-hosting-analyser-queryperf\/\">Journal des requ\u00eates lent<\/a>. Ensuite, je compare EXPLAIN avec EXPLAIN ANALYZE afin de mettre c\u00f4te \u00e0 c\u00f4te le plan et la r\u00e9alit\u00e9. J\u2019adapte la strat\u00e9gie d\u2019indexation aux clauses WHERE, JOIN et ORDER BY ; j\u2019oriente les index composites vers les points d\u2019acc\u00e8s les plus fr\u00e9quents. Je n\u2019utilise FORCE INDEX que lorsque l\u2019optimiseur choisit le mauvais candidat malgr\u00e9 des statistiques correctes.<\/p>\n\n<p>Chaque \u00e9tape implique de veiller \u00e0 la <strong>Statistiques<\/strong>: ANALYZE TABLE sur des tables tr\u00e8s sollicit\u00e9es, histogrammes pour les distributions asym\u00e9triques. Je simplifie les sous-requ\u00eates inutiles, je mat\u00e9rialise les r\u00e9sultats interm\u00e9diaires si n\u00e9cessaire et je supprime les anciennes solutions de contournement. En cas de mat\u00e9riel sp\u00e9cifique, je v\u00e9rifie les optimizer_costs afin que le mod\u00e8le en microsecondes soit correct. Je documente chaque modification \u00e0 l'aide de valeurs \u00ab avant\/apr\u00e8s \u00bb afin que son effet reste tra\u00e7able \u00e0 long terme.<\/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\/mariadb_query_optimizer_8390.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Probl\u00e8mes courants li\u00e9s aux optimiseurs et leurs solutions<\/h2>\n\n<p>Si EXPLAIN type=ALL s'affiche alors que le champ \u00ab possible_keys \u00bb est rempli, je commence par v\u00e9rifier <strong>S\u00e9lectivit\u00e9<\/strong>. Il arrive souvent que l'ordre des colonnes dans l'index composite ne soit pas adapt\u00e9 ou qu'une fonction emp\u00eache l'utilisation de l'index. Dans ce cas, j\u2019inverse l\u2019ordre, je supprime les fonctions g\u00eanantes ou je fractionne les pr\u00e9dicats. Si l\u2019ordre des jointures est incorrect, je v\u00e9rifie s\u2019il est possible d\u2019effectuer un filtrage en amont, par exemple en faisant passer en premier la table la plus s\u00e9lective. Je convertis les sous-requ\u00eates, lorsque cela s\u2019av\u00e8re judicieux, en jointures ou en tables TEMPORARY.<\/p>\n\n<p>Je reconnais \u00e9galement les mauvaises d\u00e9cisions \u00e0 des r\u00e9sultats tr\u00e8s divergents <strong>lignes<\/strong> entre le plan et la r\u00e9alit\u00e9. Dans ce cas, la commande ANALYZE TABLE ou un histogramme sur la colonne concern\u00e9e peut s'av\u00e9rer utile. Si m\u00eame des statistiques correctes ne permettent pas d'atteindre l'objectif, j'envisage d'utiliser des hints explicites. Au pr\u00e9alable, je m\u2019assure de disposer de contre-v\u00e9rifications et de valeurs mesur\u00e9es afin que les versions ult\u00e9rieures de l\u2019optimiseur ne soient pas ralenties par des param\u00e8tres enregistr\u00e9s. La rigueur dans la documentation porte ici ses fruits.<\/p>\n\n<h2>Contexte de l'h\u00e9bergement et aspects op\u00e9rationnels<\/h2>\n\n<p>La qualit\u00e9 des requ\u00eates et l'infrastructure doivent \u00eatre adapt\u00e9es l'une \u00e0 l'autre, sinon l'application ne sert \u00e0 rien <strong>Potentiel<\/strong>. Des SSD rapides, des caches coh\u00e9rents et une configuration soign\u00e9e constituent la base sur laquelle l'Optimizer prend de bonnes d\u00e9cisions. Un trafic intense ne tol\u00e8re pas les analyses compl\u00e8tes ; quelques requ\u00eates mal formul\u00e9es suffisent \u00e0 ralentir des syst\u00e8mes entiers. Pour les environnements MySQL\/MariaDB en production, voici quelques conseils pratiques tels que <a href=\"https:\/\/webhosting.de\/fr\/mysql-optimizer-query-hosting-optimisation-serverboost\/\">Optimiseur MySQL<\/a> Des pistes de r\u00e9flexion utiles sur la combinaison entre plan et plateforme. En prenant en compte cet aspect, on \u00e9vite les goulots d'\u00e9tranglement avant qu'ils ne s'aggravent.<\/p>\n\n<p>J'associe toujours l'analyse des pr\u00e9visions \u00e0 des indicateurs relatifs \u00e0 <strong>E\/S<\/strong>, la latence et la concurrence. Si les valeurs ne correspondent pas au mod\u00e8le de co\u00fbts pr\u00e9vu, je v\u00e9rifie les param\u00e8tres. Ensuite, j'examine la taille des tampons, les charges de travail parall\u00e8les et la r\u00e9partition des ensembles les plus consult\u00e9s. Cette approche permet d'assurer un fonctionnement harmonieux des requ\u00eates et des ressources, et de ma\u00eetriser les pics de trafic.<\/p>\n\n<h2>Les jointures et les chemins d'acc\u00e8s dans la pratique<\/h2>\n\n<p>Je dissipe de nombreux malentendus en expliquant que <strong>Types d'acc\u00e8s<\/strong> les mettrais d\u00e9lib\u00e9r\u00e9ment en balance. Un <em>plage<\/em>- ou bien <em>ref<\/em>-L'acc\u00e8s fonctionne presque toujours <em>TOUT<\/em>. Dans le cas de relations avec des cl\u00e9s uniques (<em>eq_ref<\/em>) les plans sont particuli\u00e8rement solides. Je v\u00e9rifie \u00e9galement si un <strong>Indice de couverture<\/strong> qui traite int\u00e9gralement la requ\u00eate : si toutes les colonnes n\u00e9cessaires figurent dans l'index, MariaDB \u00e9vite ainsi des acc\u00e8s co\u00fbteux aux tables. <strong>Index Condition Pushdown (ICP)<\/strong> permet de v\u00e9rifier des conditions WHERE suppl\u00e9mentaires d\u00e8s la phase d'indexation, ce qui r\u00e9duit le nombre de lignes renvoy\u00e9es et les op\u00e9rations d'E\/S.<\/p>\n\n<p>Sur <strong>Fusion d'index<\/strong> MariaDB peut combiner plusieurs index (intersection\/union). Cela s'av\u00e8re utile pour les pr\u00e9dicats \u00ab OR \u00bb ou plusieurs conditions de s\u00e9lection, mais s'av\u00e8re souvent plus lent qu'un index composite bien choisi. J'\u00e9value \u00e9galement <strong>MRR<\/strong> (lecture multi-port\u00e9e) et <strong>BKA<\/strong> (Batched Key Access). MRR trie les cl\u00e9s primaires \u00e0 lire afin de lisser les E\/S al\u00e9atoires ; BKA regroupe les recherches de jointure et s'av\u00e8re particuli\u00e8rement efficace dans le cas de jointures non couvertes. En pratique, je teste BKA\/MRR via optimizer_switch et je v\u00e9rifie avec EXPLAIN ANALYZE si les profils d\u2019E\/S diminuent. Si, en revanche, MariaDB recourt au <strong>Boucle imbriqu\u00e9e de blocs<\/strong> (BNL), il est g\u00e9n\u00e9ralement plus avantageux d'augmenter la taille du tampon de jointure (join_buffer_size) \u2013 ou de proc\u00e9der \u00e0 une r\u00e9\u00e9criture permettant des jointures par index.<\/p>\n\n<pre><code>-- Exemple : index composite pour jointure + filtre + tri\nCREATE INDEX ix_orders_cust_status_created\n  ON orders (customer_id, status, created_at);\n\n-- Acc\u00e8s type\nSELECT *\nFROM orders o\nJOIN customers c ON c.id = o.customer_id\nWHERE o.status = 'open' AND o.created_at &gt;= '2026-01-01'\nORDER BY o.created_at DESC\nLIMIT 50;\n<\/code><\/pre>\n\n<p>Gr\u00e2ce \u00e0 l'index ci-dessus, l'optimiseur peut choisir l'ordre le plus s\u00e9lectif, \u00e9valuer les filtres d\u00e8s le d\u00e9but et effectuer le tri souvent sans avoir recours \u00e0 un tri sur fichier suppl\u00e9mentaire.<\/p>\n\n<h2>ORDER BY, GROUP BY, tri sur fichier et tables temporaires<\/h2>\n\n<p>Le tri et l'agr\u00e9gation prennent du temps. Je veille \u00e0 ce que <strong>ORDER BY<\/strong> et <strong>GROUP BY<\/strong> peuvent s'ex\u00e9cuter selon l'ordre de l'index. Cela fonctionne si le pr\u00e9fixe et la direction correspondent exactement. Sinon, une <strong>Tri de fichiers<\/strong> avec un tampon de tri (sort_buffer_size) et, le cas \u00e9ch\u00e9ant, une table temporaire. Si l'ensemble des r\u00e9sultats contient des colonnes TEXT\/BLOB larges, MariaDB est plus rapide. <em>sur disque<\/em> Les tables TEMP (Aria). Je prends des mesures pr\u00e9ventives en ne s\u00e9lectionnant que les colonnes n\u00e9cessaires, en ne rechargeant les champs volumineux qu'\u00e0 la fin ou en utilisant des pr\u00e9fixes dont la longueur est limit\u00e9e.<\/p>\n\n<p>Pour les agr\u00e9gations, j'utilise, dans la mesure du possible, <strong>Analyse par index libre<\/strong> (par exemple, GROUP BY sur la partie principale de l'index) et je choisis des index composites le long du regroupement. Lorsque les r\u00e9sultats interm\u00e9diaires deviennent volumineux, une mat\u00e9rialisation avec des cl\u00e9s pertinentes s'adapte mieux qu'une seule m\u00e9ga-jointure. Je mesure r\u00e9guli\u00e8rement les m\u00e9triques des gestionnaires et les compteurs Created_tmp_* afin de d\u00e9tecter les points chauds li\u00e9s au tri et aux tables temporaires.<\/p>\n\n<h2>Sous-requ\u00eates, semi-jointures et mat\u00e9rialisation<\/h2>\n\n<p>De nombreuses sous-requ\u00eates peuvent \u00eatre reformul\u00e9es efficacement lors de la pr\u00e9paration. Les constructions IN\/EXISTS peuvent \u00eatre remplac\u00e9es par <strong>Semi-jointure<\/strong> fonctionnent, avec des strat\u00e9gies telles que la mat\u00e9rialisation ou LooseScan. Je v\u00e9rifie si l'optimiseur est un <strong>derived_merge<\/strong> a pu \u00eatre ex\u00e9cut\u00e9e : si une table d\u00e9riv\u00e9e (ou une CTE WITH) est int\u00e9gr\u00e9e dans le plan externe, ses index sont directement disponibles. Si cela ne fonctionne pas, la sous-requ\u00eate se retrouve dans une table temporaire \u2013 je lui attribue alors, si possible, une cl\u00e9 (par exemple via SELECT DISTINCT\/ORDER BY sur des colonnes cl\u00e9s), afin que les jointures ne se perdent pas dans le n\u00e9ant.<\/p>\n\n<pre><code>-- Exemple : EXISTS \u00e0 la place de IN et table d\u00e9riv\u00e9e compatible avec la fusion\nSELECT o.id\nFROM orders o\nWHERE EXISTS (\n  SELECT 1 FROM payments p\n  WHERE p.order_id = o.id AND p.state = 'captured'\n);\n\n-- D\u00e9rivation avec des cl\u00e9s uniques\nWITH paid_orders AS (\n  SELECT DISTINCT order_id\n  FROM payments\n  WHERE state = 'captured'\n)\nSELECT o.*\nFROM orders o\nJOIN paid_orders po ON po.order_id = o.id;\n<\/code><\/pre>\n\n<p>J'utilise la commande EXPLAIN FORMAT=JSON pour v\u00e9rifier si <strong>mat\u00e9rialis\u00e9<\/strong> ou <strong>sous-requ\u00eate d\u00e9pendante<\/strong> a \u00e9t\u00e9 s\u00e9lectionn\u00e9 et si des conditions (<strong>pouss\u00e9e conditionnelle<\/strong>) agir suffisamment t\u00f4t.<\/p>\n\n<h2>Partitionnement et \u00e9lagage<\/h2>\n\n<p>Le partitionnement ne remplace pas les index, mais il peut am\u00e9liorer la <strong>Volume de donn\u00e9es par acc\u00e8s<\/strong> r\u00e9duire consid\u00e9rablement. L'optimiseur n'effectue une \u00e9lagage correct que si le pr\u00e9dicat satisfait le <strong>Cl\u00e9 de partition<\/strong> correspond clairement et n'est pas masqu\u00e9 par des fonctions. J'\u00e9vite donc d'utiliser des expressions telles que DATE(created_at) dans la clause WHERE sur des tables partitionn\u00e9es et j'utilise plut\u00f4t des limites de plage. La commande EXPLAIN indique quelles partitions sont lues ; des plages trop larges sont le signe d'un mauvais \u00e9lagage.<\/p>\n\n<p>Un trop grand nombre de petites partitions augmente la charge de travail li\u00e9e \u00e0 la planification. Je choisis donc une granularit\u00e9 pertinente (par exemple, mensuelle plut\u00f4t que quotidienne), je veille \u00e0 ce que les statistiques de chaque partition soient \u00e0 jour (ANALYZE PARTITION) et je v\u00e9rifie si les index importants sont pr\u00e9sents localement dans les partitions. Dans le cadre de projets de migration, je tiens compte de l\u2019impact sur la r\u00e9plication et la sauvegarde : ces deux facteurs influencent le degr\u00e9 d\u2019agressivit\u00e9 de ma partitionnalisation.<\/p>\n\n<h2>Sargabilit\u00e9 et mod\u00e8les de r\u00e9\u00e9criture<\/h2>\n\n<p>Le levier le plus simple reste <strong>Sargabilit\u00e9<\/strong> \u2013 Conditions permettant d'exploiter les index. J'\u00e9vite d'utiliser des fonctions sur les colonnes dans la clause WHERE, je ram\u00e8ne les constantes du c\u00f4t\u00e9 des colonnes et, si n\u00e9cessaire, je d\u00e9compose les conditions \u00ab OR \u00bb en <strong>UNION ALL<\/strong>. Pour les recherches LIKE sans ancrage initial (\" %foo \"), un index BTREE ne sert \u00e0 rien ; dans ce cas, j'envisage d'utiliser la recherche plein texte ou un service de recherche adapt\u00e9. Pour les calculs, j'utilise <strong>colonnes g\u00e9n\u00e9r\u00e9es index\u00e9es<\/strong>, afin que l'optimiseur puisse retrouver la logique dans l'index.<\/p>\n\n<pre><code>-- Anti-mod\u00e8le : fonction sur une colonne\nWHERE DATE(created_at) = '2026-08-01'\n-- Mieux : plage sur la valeur brute\nWHERE created_at &gt;= '2026-08-01' AND created_at &lt; &#039;2026-08-02&#039;\n\n-- Anti-mod\u00e8le : l&#039;op\u00e9rateur OR emp\u00eache l&#039;utilisation d&#039;un index\nWHERE status = &#039;open&#039; OR customer_id = 42\n-- Meilleure solution : deux requ\u00eates avec UNION ALL et chacune son propre index\n(SELECT ... WHERE status = &#039;open&#039;)\nUNION ALL\n(SELECT ... WHERE customer_id = 42&#039;);\n<\/code><\/pre>\n\n<p>En ce qui concerne les indices composites, je consid\u00e8re que <strong>r\u00e8gle du pr\u00e9fixe de gauche<\/strong> Respectez scrupuleusement cette r\u00e8gle : triez les colonnes en fonction de leur s\u00e9lectivit\u00e9 et du tri qui sera n\u00e9cessaire par la suite. Si j\u2019ai besoin d\u2019un ORDER BY d\u00e9croissant, j\u2019en tiens compte dans la structure de l\u2019index \u2013 cela m\u2019\u00e9vite ainsi le tri sur fichier.<\/p>\n\n<h2>Commutateur d'optimisation et r\u00e9glage fin des co\u00fbts<\/h2>\n\n<p>Avant de me pencher sur les requ\u00eates, je v\u00e9rifie <strong>optimizer_switch<\/strong> et des tampons de m\u00e9moire. Des fonctionnalit\u00e9s telles que <em>mrr<\/em>, <em>batched_key_access<\/em>, <em>index_merge<\/em>, <em>semijoin<\/em>, <em>derived_merge<\/em> ou <em>condition_pushdown_for_derived<\/em> peuvent \u00eatre ajust\u00e9s \u00e0 chaque session. J'active des candidats de mani\u00e8re cibl\u00e9e pour une session de test, j'effectue des mesures avec EXPLAIN ANALYZE et je reviens en arri\u00e8re si l'effet escompt\u00e9 ne se produit pas. Le chemin de jointure b\u00e9n\u00e9ficie d'une quantit\u00e9 suffisante de <strong>join_buffer_size<\/strong>; grandes vari\u00e9t\u00e9s de <strong>sort_buffer_size<\/strong>. Parall\u00e8lement, je surveille les tampons par rapport \u00e0 la concurrence, afin que le serveur ne se retrouve pas en situation de swap sous une charge parall\u00e8le.<\/p>\n\n<p>Au niveau des co\u00fbts, j'ajuste, si n\u00e9cessaire, les \u00e9l\u00e9ments d\u00e9j\u00e0 mentionn\u00e9s <strong>co\u00fbts_de_l'optimiseur<\/strong> en microsecondes. Ma ligne directrice : des \u00e9tapes modestes et r\u00e9versibles, avec des points de mesure document\u00e9s. J'utilise <strong>LAST_QUERY_COST<\/strong> pour v\u00e9rifier la plausibilit\u00e9 et refaire des mesures avec des valeurs de param\u00e8tres r\u00e9alistes, car les plans peuvent d\u00e9pendre fortement de constantes concr\u00e8tes.<\/p>\n\n<h2>Stabilit\u00e9 des plans, r\u00e9gressions et flux de travail en \u00e9quipe<\/h2>\n\n<p>M\u00eame un bon plan peut \u00eatre compromis par l'augmentation du volume de donn\u00e9es ou un changement de version <strong>basculer<\/strong>. Je m'assure donc de disposer d'informations sur les plans d'ex\u00e9cution : hachages de requ\u00eates, JSON EXPLAIN, extraits de traces de l'optimiseur et dur\u00e9es d'ex\u00e9cution d'EXPLAIN ANALYZE. Les modifications apport\u00e9es aux index et les r\u00e9\u00e9critures sont effectu\u00e9es sous forme de pull requests, accompagn\u00e9es de justificatifs \u00ab avant\/apr\u00e8s \u00bb. Dans les environnements CI\/CD, je teste automatiquement les requ\u00eates critiques sur des ensembles de donn\u00e9es repr\u00e9sentatifs. C'est ainsi que je <strong>Plans de r\u00e9gression<\/strong> t\u00f4t.<\/p>\n\n<p>Pour les cas d\u00e9licats, je consid\u00e8re que <strong>Conseils<\/strong> (FORCE INDEX, STRAIGHT_JOIN, optimizer_switch par requ\u00eate) sont disponibles en dernier recours, mais utilisez-les avec parcimonie et en leur fixant une date d'expiration. Il vaut mieux rem\u00e9dier aux causes profondes : statistiques, index, formulation. Au sein des \u00e9quipes, un guide succinct sur la \u00ab sargability \u00bb, la conception des index et la rigueur des mesures garantit que les nouvelles fonctionnalit\u00e9s n\u2019int\u00e8grent pas, \u00e0 l\u2019insu de tous, des sources de frustration en mati\u00e8re de performances.<\/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\/mariadb-query-optimizer-7832.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Bilan succinct : du projet \u00e0 la r\u00e9alisation<\/h2>\n\n<p>Celui qui a <strong>Plan<\/strong> permet de comprendre et de contr\u00f4ler les performances. Les phases \u00ab Parsing \u00bb, \u00ab Preparing \u00bb, \u00ab Optimizing \u00bb et \u00ab Executing \u00bb permettent d'identifier les sources de perte de temps. Le mod\u00e8le de co\u00fbt bas\u00e9 sur le temps disponible \u00e0 partir de la version 11.0, ainsi que des statistiques et des histogrammes r\u00e9guli\u00e8rement mis \u00e0 jour, rendent les estimations fiables. EXPLAIN, EXPLAIN ANALYZE et l\u2019Optimizer Trace apportent une transparence que je traduis en mesures concr\u00e8tes. Gr\u00e2ce \u00e0 une strat\u00e9gie d\u2019indexation rigoureuse, une conception claire des requ\u00eates et une infrastructure adapt\u00e9e, les requ\u00eates MariaDB fournissent syst\u00e9matiquement des r\u00e9ponses rapides.<\/p>","protected":false},"excerpt":{"rendered":"<p>D\u00e9couvrez le fonctionnement interne de l'optimiseur de requ\u00eates MariaDB, comment analyser le plan d'ex\u00e9cution SQL \u00e0 l'aide de la commande EXPLAIN et comment mettre en \u0153uvre des techniques pratiques d'optimisation de bases de donn\u00e9es, avec notamment des conseils pour des applications web performantes.<\/p>","protected":false},"author":1,"featured_media":20923,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[781],"tags":[],"class_list":["post-20930","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":"132","_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":"MariaDB Optimizer","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":"20923","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/posts\/20930","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/comments?post=20930"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/posts\/20930\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/media\/20923"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/media?parent=20930"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/categories?post=20930"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/fr\/wp-json\/wp\/v2\/tags?post=20930"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}