{"id":7387,"date":"2019-06-25T09:34:21","date_gmt":"2019-06-25T08:34:21","guid":{"rendered":"http:\/\/blog.capdata.fr\/?p=7387"},"modified":"2019-09-13T10:38:53","modified_gmt":"2019-09-13T09:38:53","slug":"nouveautes-mysql-8-0-les-histogrammes","status":"publish","type":"post","link":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/","title":{"rendered":"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes"},"content":{"rendered":"<a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F7387&#038;text=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F7387&#038;title=Nouveaut%C3%A9s%20MySQL%208.0%20%3A%20Les%20Histogrammes\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Nouveaut%C3%A9s%20MySQL%208.0%20%3A%20Les%20Histogrammes&#038;body=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20:%20https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F7387\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/mail.png\" \/><\/a><h3>Ce quatri\u00e8me article concerne les statistiques d&#8217;histogramme.<\/h3>\n<p>Depuis la version 5.6, il est possible de cr\u00e9er des statistiques persist\u00e9s avec l&#8217;option innodb_stats_persistent=1 (par d\u00e9faut depuis la 5.6.6) ou par table avec stats_persistent=1.<\/p>\n<p>Les statistiques sont alors stock\u00e9es dans la colonne <strong>last_update<\/strong> des tables <strong>mysql.innodb_table_ stats<\/strong> et <strong>mysql.innodb_index_stats<\/strong>.<\/p>\n<p>Contrairement \u00e0 MyISAM, les statistiques en InnoDB sont calcul\u00e9es seulement sur un \u00e9chantillon et pas la totalit\u00e9 des valeurs dans la colonne (innodb_stats_persistent_sample_pages ou stats_sample_pages de CREATE TABLE ou ALTER TABLE).<\/p>\n<p>MariaDB \u00e9tait un des seul moteur \u00e0 les impl\u00e9menter en 2017 depuis la 10.0.2 (mysql.column_stats). Maintenant, avec MySQL 8, nous avons \u00e9galement l&#8217;impl\u00e9mentation d&#8217;histogrammes.<\/p>\n<p>Par d\u00e9faut depuis 5.6.6, les statistiques persist\u00e9s seront recalcul\u00e9es automatiquement avec <strong>innodb_stats_auto_recalc=1<\/strong>, lorsque plus de 10% des valeurs de la table auront \u00e9t\u00e9 modifi\u00e9es. Le recalcul automatique peut aussi \u00eatre param\u00e9tr\u00e9 par table en utilisant le mot-cl\u00e9 <strong>stats_auto_recalc<\/strong> de CREATE TABLE ou ALTER TABLE.<\/p>\n<p>Les statistiques sont ensuite recalcul\u00e9es en arri\u00e8re plan et de mani\u00e8re asynchrone, donc elles peuvent ne pas \u00eatre imm\u00e9diatement disponibles. Pour assurer une disponibilit\u00e9 certaine des statistiques, il faut quand m\u00eame programmer des ANALYZE TABLE r\u00e9guliers, surtout suite \u00e0 des changements importants de donn\u00e9es (chargements, purges, etc&#8230;).<\/p>\n<p>Depuis la 8.0.3, on a la possibilit\u00e9 de cr\u00e9er des statistiques d&#8217;histogramme pour en fournir plus \u00e0 l&#8217;optimizer.<\/p>\n<p>Nous allons donc voir dans cet article, comment cr\u00e9er et voir des statistiques d&#8217;histogrammes ainsi que leurs utilit\u00e9s.<\/p>\n<p>L&#8217;optimizer de requ\u00eates permet de traduire une requ\u00eate en un plan d&#8217;ex\u00e9cution le plus optimal possible. Cependant, l&#8217;optimizer peut ne pas trouver le meilleur plan d&#8217;ex\u00e9cution pour cette requ\u00eate et donc d\u00e9grader son temps d&#8217;ex\u00e9cution. Ce mauvais plan choisit par l&#8217;optimizer peut \u00eatre d\u00fb \u00e0 un manque d&#8217;informations sur la table en question (nombre de lignes, nombre de valeurs distinctes &#8230;).<\/p>\n<p>Comment peut-on savoir si des statistiques peuvent \u00eatre importantes pour les donn\u00e9es de tables ?<\/p>\n<p>Nous allons donc le voir dans l&#8217;exemple ci-dessous.<\/p>\n<p>On va cr\u00e9er une table travail afin de faire des tests de SELECT sur un champ de type TIME.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; create table travail (\r\n-&gt; personne_id mediumint(8),\r\n-&gt; heure_de_travail TIME,\r\n-&gt; localisation varchar(30) NOT NULL);\r\nQuery OK, 0 rows affected (1.24 sec)\r\n\r\nmysql&gt; select * from travail where heure_de_travail between &quot;08:00:00&quot; and &quot;10:00:00&quot;;\r\n+-------------+------------------+--------------+\r\n| personne_id | heure_de_travail | localisation |\r\n+-------------+------------------+--------------+\r\n|           1 | 08:00:00         | Nantes       |\r\n|           1 | 09:00:00         | Nantes       |\r\n|           3 | 09:00:00         | Rennes       |\r\n|           4 | 10:00:00         | Saint Brieuc |\r\n|           1 | 08:00:00         | Bordeaux     |\r\n|           5 | 08:00:00         | Lyon         |\r\n|           5 | 09:00:00         | Lyon         |\r\n|           6 | 09:00:00         | Paris        |\r\n|           7 | 10:00:00         | Boulogne     |\r\n|           7 | 09:00:00         | Boulogne     |\r\n|           8 | 10:00:00         | Londres      |\r\n|           9 | 10:00:00         | Berlin       |\r\n|           9 | 09:00:00         | Berlin       |\r\n|          10 | 08:00:00         | Amsterdam    |\r\n+-------------+------------------+--------------+\r\n14 rows in set (0.39 sec)\r\n\r\nmysql&gt; select * from travail where heure_de_travail between &quot;10:00:00&quot; and &quot;12:00:00&quot;;\r\n+-------------+------------------+--------------+\r\n| personne_id | heure_de_travail | localisation |\r\n+-------------+------------------+--------------+\r\n|           4 | 10:00:00         | Saint Brieuc |\r\n|           7 | 10:00:00         | Boulogne     |\r\n|           8 | 11:00:00         | Londres      |\r\n|           8 | 10:00:00         | Londres      |\r\n|           9 | 10:00:00         | Berlin       |\r\n+-------------+------------------+--------------+\r\n5 rows in set (0.00 sec)<\/pre>\n<p>Par exemple, si on ex\u00e9cute diff\u00e9rentes requ\u00eates sur la table travail avec une condition sur la colonne <em>heure_de_travail<\/em>, nous n&#8217;aurons pas le m\u00eame nombre de lignes retourn\u00e9es. En effet, la premi\u00e8re requ\u00eate nous retournera plus de lignes car il y a plus de personnes travaillant dans l&#8217;horaire 08h00-10h00 plut\u00f4t que 10h00-12h00 dans la seconde requ\u00eate.<\/p>\n<p>Si aucune statistique n&#8217;est mise en place pour cette table travail, l&#8217;optimizer va supposer que les valeurs de <em>heure_de_travail <\/em>sont toutes \u00e9gales, m\u00eame si les valeurs sont comprises entre 23h et 6h par exemple.<br \/>\nIl faut donc informer l&#8217;optimizer de cette diff\u00e9rence dans les donn\u00e9es et cela en cr\u00e9ant des statistiques d&#8217;histogramme pour cette colonne <em>heure_de_travail<\/em>.<\/p>\n<p>Un histogramme permet de donner une approximation de la distribution de donn\u00e9es pour une colonne.<\/p>\n<p>Nous allons faire maintenant nos tests sur 2 tables que l&#8217;on a cr\u00e9\u00e9 : personne et ville.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; select table_schema, table_name, engine, version, create_time, update_time, check_time from information_schema.tables where table_schema = 'world' and table_name in ('personne','ville');\r\n+--------------+------------+--------+---------+---------------------+-------------+------------+\r\n| TABLE_SCHEMA | TABLE_NAME | ENGINE | VERSION | CREATE_TIME | UPDATE_TIME | CHECK_TIME |\r\n+--------------+------------+--------+---------+---------------------+-------------+------------+\r\n| world | personne | InnoDB | 10 | 2019-03-18 11:55:58 | NULL | NULL |\r\n| world | ville | InnoDB | 10 | 2019-03-21 12:21:13 | NULL | NULL |\r\n+--------------+------------+--------+---------+---------------------+-------------+------------+\r\n2 rows in set (0.00 sec)<\/pre>\n<p>J&#8217;ai ins\u00e9r\u00e9 10 lignes dans la table <em>ville<\/em>. Ensuite, j&#8217;ai supprim\u00e9 2 indexes sur la table <em>ville <\/em>et j&#8217;en ai cr\u00e9\u00e9 3 autres dont 1 cl\u00e9 primaire. Ici, la somme des indexes (sans compter la cl\u00e9 primaire) est pourtant de 0 pour la table <em>world.ville<\/em>. Enfin, j&#8217;ai \u00e9galement modifi\u00e9 les noms de ville pour la table personne en enlevant certains accents et trait d&#8217;union le 21\/03\/2019 peu avant 12h00.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-02-27 15:27:59 | 10 | 1 | 4 |\r\n| world | ville | 2019-03-21 12:20:52 | 10 | 1 | 0 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n2 rows in set (0.13 sec)\r\n\r\nmysql&gt; select * from mysql.innodb_index_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+\r\n| database_name | table_name | index_name | last_update | stat_name | stat_value | sample_size | stat_description |\r\n+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+\r\n| world | personne | PRIMARY | 2019-02-27 15:27:59 | n_diff_pfx01 | 10 | 1 | personne_id |\r\n| world | personne | PRIMARY | 2019-02-27 15:27:59 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | PRIMARY | 2019-02-27 15:27:59 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_age | 2019-02-27 15:27:59 | n_diff_pfx01 | 6 | 1 | age |\r\n| world | personne | idx_personne_age | 2019-02-27 15:27:59 | n_diff_pfx02 | 10 | 1 | age,personne_id |\r\n| world | personne | idx_personne_age | 2019-02-27 15:27:59 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_age | 2019-02-27 15:27:59 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_nom | 2019-02-27 15:27:59 | n_diff_pfx01 | 10 | 1 | nom |\r\n| world | personne | idx_personne_nom | 2019-02-27 15:27:59 | n_diff_pfx02 | 10 | 1 | nom,personne_id |\r\n| world | personne | idx_personne_nom | 2019-02-27 15:27:59 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_nom | 2019-02-27 15:27:59 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_prenom | 2019-02-27 15:27:59 | n_diff_pfx01 | 10 | 1 | prenom |\r\n| world | personne | idx_personne_prenom | 2019-02-27 15:27:59 | n_diff_pfx02 | 10 | 1 | prenom,personne_id |\r\n| world | personne | idx_personne_prenom | 2019-02-27 15:27:59 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_prenom | 2019-02-27 15:27:59 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_ville | 2019-02-27 15:27:59 | n_diff_pfx01 | 10 | 1 | ville |\r\n| world | personne | idx_personne_ville | 2019-02-27 15:27:59 | n_diff_pfx02 | 10 | 1 | ville,personne_id |\r\n| world | personne | idx_personne_ville | 2019-02-27 15:27:59 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_ville | 2019-02-27 15:27:59 | size | 1 | NULL | Number of pages in the index |\r\n| world | ville | PRIMARY | 2019-03-21 12:20:52 | n_diff_pfx01 | 10 | 1 | ville_id |\r\n| world | ville | PRIMARY | 2019-03-21 12:20:52 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | ville | PRIMARY | 2019-03-21 12:20:52 | size | 1 | NULL | Number of pages in the index |\r\n| world | ville | idx_ville_cp | 2019-03-21 12:20:52 | n_diff_pfx01 | 9 | 1 | code_postal |\r\n| world | ville | idx_ville_cp | 2019-03-21 12:20:52 | n_diff_pfx02 | 10 | 1 | code_postal,ville_id |\r\n| world | ville | idx_ville_cp | 2019-03-21 12:20:52 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | ville | idx_ville_cp | 2019-03-21 12:20:52 | size | 1 | NULL | Number of pages in the index |\r\n| world | ville | idx_ville_nom | 2019-03-21 12:20:52 | n_diff_pfx01 | 10 | 1 | nom |\r\n| world | ville | idx_ville_nom | 2019-03-21 12:20:52 | n_diff_pfx02 | 10 | 1 | nom,ville_id |\r\n| world | ville | idx_ville_nom | 2019-03-21 12:20:52 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | ville | idx_ville_nom | 2019-03-21 12:20:52 | size | 1 | NULL | Number of pages in the index |\r\n+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+<\/pre>\n<p>La table <em>ville <\/em>et l&#8217;ajout de donn\u00e9es \u00e0 celle-ci a \u00e9t\u00e9 fait autour de 12h00.<br \/>\nLes derni\u00e8res statistiques pour la table <em>personne <\/em>datent du 27\/02\/2019 15h27 et du 21\/03\/2019 12h20 pour la table <em>ville<\/em>.<\/p>\n<p>Je lance un ANALYZE TABLE tout simple, sans options sur les tables <em>personne <\/em>et <em>ville<\/em>.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; analyze table world.personne;\r\n+----------------+---------+----------+----------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+----------------+---------+----------+----------+\r\n| world.personne | analyze | status | OK |\r\n+----------------+---------+----------+----------+\r\n1 row in set (0.43 sec)\r\n\r\nmysql&gt; analyze table world.ville;\r\n+-------------+---------+----------+----------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+-------------+---------+----------+----------+\r\n| world.ville | analyze | status | OK |\r\n+-------------+---------+----------+----------+\r\n1 row in set (0.13 sec)\r\n\r\nmysql&gt; select table_schema, table_name, engine, version, create_time, update_time, check_time from information_schema.tables where table_schema = 'world' and table_name in ('personne','ville');\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n| TABLE_SCHEMA | TABLE_NAME | ENGINE | VERSION | CREATE_TIME | UPDATE_TIME | CHECK_TIME |\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n| world | personne | InnoDB | 10 | 2019-03-18 11:55:58 | 2019-03-21 11:59:42 | NULL |\r\n| world | ville | InnoDB | 10 | 2019-03-21 12:21:13 | NULL | NULL |\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n2 rows in set (0.00 sec)<\/pre>\n<p>On constate que l&#8217;utilisation du ANALYZE TABLE a mis \u00e0 jour la colonne UPDATE_TIME au 21\/03\/2019 \u00e0 11h59 pour la table <em>personne<\/em>, moment ou j&#8217;ai fait les modifications de certains noms de ville.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-03-21 14:59:47 | 10 | 1 | 4 |\r\n| world | ville | 2019-03-21 14:59:54 | 10 | 1 | 2 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n2 rows in set (0.00 sec)\r\n\r\nmysql&gt; select * from mysql.innodb_index_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+\r\n| database_name | table_name | index_name | last_update | stat_name | stat_value | sample_size | stat_description |\r\n+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+\r\n| world | personne | PRIMARY | 2019-03-21 14:59:47 | n_diff_pfx01 | 10 | 1 | personne_id |\r\n| world | personne | PRIMARY | 2019-03-21 14:59:47 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | PRIMARY | 2019-03-21 14:59:47 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_age | 2019-03-21 14:59:47 | n_diff_pfx01 | 6 | 1 | age |\r\n| world | personne | idx_personne_age | 2019-03-21 14:59:47 | n_diff_pfx02 | 10 | 1 | age,personne_id |\r\n| world | personne | idx_personne_age | 2019-03-21 14:59:47 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_age | 2019-03-21 14:59:47 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_nom | 2019-03-21 14:59:47 | n_diff_pfx01 | 10 | 1 | nom |\r\n| world | personne | idx_personne_nom | 2019-03-21 14:59:47 | n_diff_pfx02 | 10 | 1 | nom,personne_id |\r\n| world | personne | idx_personne_nom | 2019-03-21 14:59:47 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_nom | 2019-03-21 14:59:47 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_prenom | 2019-03-21 14:59:47 | n_diff_pfx01 | 10 | 1 | prenom |\r\n| world | personne | idx_personne_prenom | 2019-03-21 14:59:47 | n_diff_pfx02 | 10 | 1 | prenom,personne_id |\r\n| world | personne | idx_personne_prenom | 2019-03-21 14:59:47 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_prenom | 2019-03-21 14:59:47 | size | 1 | NULL | Number of pages in the index |\r\n| world | personne | idx_personne_ville | 2019-03-21 14:59:47 | n_diff_pfx01 | 9 | 1 | ville |\r\n| world | personne | idx_personne_ville | 2019-03-21 14:59:47 | n_diff_pfx02 | 10 | 1 | ville,personne_id |\r\n| world | personne | idx_personne_ville | 2019-03-21 14:59:47 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | personne | idx_personne_ville | 2019-03-21 14:59:47 | size | 1 | NULL | Number of pages in the index |\r\n| world | ville | PRIMARY | 2019-03-21 14:59:54 | n_diff_pfx01 | 10 | 1 | ville_id |\r\n| world | ville | PRIMARY | 2019-03-21 14:59:54 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | ville | PRIMARY | 2019-03-21 14:59:54 | size | 1 | NULL | Number of pages in the index |\r\n| world | ville | idx_ville_cp | 2019-03-21 14:59:54 | n_diff_pfx01 | 9 | 1 | code_postal |\r\n| world | ville | idx_ville_cp | 2019-03-21 14:59:54 | n_diff_pfx02 | 10 | 1 | code_postal,ville_id |\r\n| world | ville | idx_ville_cp | 2019-03-21 14:59:54 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | ville | idx_ville_cp | 2019-03-21 14:59:54 | size | 1 | NULL | Number of pages in the index |\r\n| world | ville | idx_ville_nom | 2019-03-21 14:59:54 | n_diff_pfx01 | 10 | 1 | nom |\r\n| world | ville | idx_ville_nom | 2019-03-21 14:59:54 | n_diff_pfx02 | 10 | 1 | nom,ville_id |\r\n| world | ville | idx_ville_nom | 2019-03-21 14:59:54 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |\r\n| world | ville | idx_ville_nom | 2019-03-21 14:59:54 | size | 1 | NULL | Number of pages in the index |\r\n+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+\r\n30 rows in set (0.00 sec)<\/pre>\n<p>Suite au ANALYZE TABLE, les tables <em>personne <\/em>et <em>ville <\/em>ainsi que leurs indexes ont vu leurs statistiques \u00eatre mises \u00e0 jour.<\/p>\n<p>Nous allons maintenant tester la cr\u00e9ation de statistiques d&#8217;histogramme.<\/p>\n<p>Mais avant tout, il faut regarder de quand date les derni\u00e8res mise \u00e0 jour de statistiques des tables <em>personne <\/em>et <em>ville<\/em>.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; select table_schema, table_name, engine, version, create_time, update_time, check_time from information_schema.tables where table_schema = 'world' and table_name in ('personne','ville');\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n| TABLE_SCHEMA | TABLE_NAME | ENGINE | VERSION | CREATE_TIME | UPDATE_TIME | CHECK_TIME |\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n| world | personne | InnoDB | 10 | 2019-03-21 15:56:19 | 2019-03-21 11:59:42 | NULL |\r\n| world | ville | InnoDB | 10 | 2019-03-21 12:21:13 | NULL | NULL |\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n2 rows in set (0.00 sec)\r\n\r\nmysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-03-21 14:59:47 | 10 | 1 | 4 |\r\n| world | ville | 2019-03-21 15:52:07 | 11 | 1 | 2 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n2 rows in set (0.00 sec)<\/pre>\n<p>On constate que les derni\u00e8res mises \u00e0 jour de statistiques datent du 21\/03\/2019 pour les tables <em>personne <\/em>et <em>ville<\/em>.<\/p>\n<p>Maintenant, je vais modifier plusieurs valeurs sur les donn\u00e9es de la colonne age et ville de la table <em>personne <\/em>ainsi que la colonne code_postal de la table <em>ville<\/em>. De plus, je vais \u00e9galement ajouter une ligne aux tables <em>ville <\/em>et <em>personne<\/em>, pour ensuite cr\u00e9er des statistiques d&#8217;histogramme sur la colonne age de la table <em>personne <\/em>et la colonne code_postal de la table <em>ville<\/em>.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; update personne set age=26 where personne_id=2;\r\nQuery OK, 1 row affected (0.16 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update personne set age=35 where personne_id=3;\r\nQuery OK, 1 row affected (0.11 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update personne set age=41 where personne_id=4;\r\nQuery OK, 1 row affected (0.08 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update personne set age=29 where personne_id=5;\r\nQuery OK, 1 row affected (0.06 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update ville set code_postal=44300 where ville_id=1;\r\nQuery OK, 1 row affected (0.12 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update ville set code_postal=44470 where ville_id=2;\r\nQuery OK, 1 row affected (0.07 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update ville set code_postal=44490 where ville_id=8;\r\nQuery OK, 1 row affected (0.09 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update ville set code_postal=44710 where ville_id=6;\r\nQuery OK, 1 row affected (0.06 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0<\/pre>\n<p>La variable autocommit \u00e9tant positionn\u00e9e par d\u00e9faut \u00e0 ON, il n&#8217;y a pas besoin de faire de commit.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; analyze table personne update histogram on ville with 16 buckets;\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n| world.personne | histogram | status | Histogram statistics created for column 'ville'. |\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n1 row in set (0.32 sec)\r\n\r\nmysql&gt; analyze table ville update histogram on code_postal with 16 buckets;\r\n+-------------+-----------+----------+--------------------------------------------------------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+-------------+-----------+----------+--------------------------------------------------------+\r\n| world.ville | histogram | status | Histogram statistics created for column 'code_postal'. |\r\n+-------------+-----------+----------+--------------------------------------------------------+\r\n1 row in set (0.15 sec)<\/pre>\n<p>Nous avons cr\u00e9\u00e9 des statistiques d&#8217;histogramme pour la colonne ville et code_postal avec 32 buckets. Le nombre de buckets doit \u00eatre sp\u00e9cifi\u00e9 quand on cr\u00e9\u00e9 un histograme et il doit \u00eatre compris entre 1 et 1024. Ce chiffre d\u00e9pend de plusieurs facteurs dont le nombre de valeurs distinctes, la qualit\u00e9 de la donn\u00e9es, le besoin de pr\u00e9cision &#8230;<\/p>\n<p>Cela ne sert donc pas \u00e0 grand chose de mettre une grande valeur mais plut\u00f4t commencer bas et augmenter plus tard si besoin est.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; select table_schema, table_name, engine, version, create_time, update_time, check_time from information_schema.tables where table_schema = 'world' and table_name in ('personne','ville');\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n| TABLE_SCHEMA | TABLE_NAME | ENGINE | VERSION | CREATE_TIME | UPDATE_TIME | CHECK_TIME |\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n| world | personne | InnoDB | 10 | 2019-03-21 15:56:19 | 2019-03-21 15:57:22 | NULL |\r\n| world | ville | InnoDB | 10 | 2019-03-21 12:21:13 | 2019-03-21 15:52:07 | NULL |\r\n+--------------+------------+--------+---------+---------------------+---------------------+------------+\r\n2 rows in set (0.12 sec)\r\n\r\nmysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-03-21 14:59:47 | 10 | 1 | 4 |\r\n| world | ville | 2019-03-27 11:40:11 | 11 | 1 | 2 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n2 rows in set (0.05 sec)<\/pre>\n<p>On constate que la mise \u00e0 jour des statistiques a \u00e9t\u00e9 faite pour la table <em>ville <\/em>gr\u00e2ce aux statistiques d&#8217;histogramme sur la colonne code_postal. Pourtant, la table <em>personne <\/em>n&#8217;a pas eu ses statistiques mises \u00e0 jour !<\/p>\n<p>Je peux voir de quand date les derni\u00e8res mises \u00e0 jour des histogrammes cr\u00e9\u00e9s pr\u00e9c\u00e9dement sur les colonnes des tables gr\u00e2ce \u00e0 la table <strong>column_statistics<\/strong> de information_schema.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; SELECT schema_name, table_name, column_name, histogram-&gt;'$.&quot;number-of-buckets-specified&quot;' as number_of_buckets, histogram-&gt;'$.&quot;sampling-rate&quot;' as sampling_rate, HISTOGRAM-&gt;'$.&quot;last-updated&quot;' as last_updated\r\n-&gt; FROM INFORMATION_SCHEMA.COLUMN_STATISTICS\r\n-&gt; WHERE SCHEMA_NAME = &quot;world&quot;\r\n-&gt; AND TABLE_NAME IN ('personne','ville');\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | number_of_buckets | sampling_rate | last_updated |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| world | personne | ville | 16 | 1.0 | 2019-03-28 08:46:42.629179 |\r\n| world | ville | code_postal | 16 | 1.0 | 2019-03-28 08:46:57.299199 |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n3 rows in set (0.00 sec)<\/pre>\n<p>Ici en version MySQL 8.0.14, les param\u00e8tres innodb_stats_persistent et innodb_stats_auto_recalc sont bien activ\u00e9s. Ce qui veut dire que dire que les statistiques d&#8217;index sont conserv\u00e9es sur disque quand innodb_stats_persistant est activ\u00e9 (par d\u00e9faut) ou lors de la cr\u00e9ation\/modification d&#8217;une table. De plus, innob_stats_auto_recalc permet de recalculer automatiquement les statistiques persistantes si les donn\u00e9es ont \u00e9t\u00e9 modifi\u00e9es r\u00e9cemment avec un seuil de 10% des lignes de la table.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; show global variables like 'innodb_stats_persistent';\r\n+-------------------------+-------+\r\n| Variable_name | Value |\r\n+-------------------------+-------+\r\n| innodb_stats_persistent | ON |\r\n+-------------------------+-------+\r\n1 row in set (0.06 sec)\r\n\r\nmysql&gt; show global variables like 'innodb_stats_auto_recalc';\r\n+--------------------------+-------+\r\n| Variable_name | Value |\r\n+--------------------------+-------+\r\n| innodb_stats_auto_recalc | ON |\r\n+--------------------------+-------+\r\n1 row in set (0.00 sec)<\/pre>\n<p>Je d\u00e9sactive le recalcul automatique des statistiques si 10% de la table est modifi\u00e9e.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">set global innodb_stats_auto_recalc=OFF;<\/pre>\n<p>Maintenant, je mets \u00e0 jour les donn\u00e9es de la personne et regarde si les statistiques ont \u00e9t\u00e9 mises \u00e0 jour automatiquement.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; update personne set ville ='Paris' where personne_id in (7,10,2);\r\nQuery OK, 3 rows affected (0.13 sec)\r\nRows matched: 3 Changed: 3 Warnings: 0\r\n\r\nmysql&gt; update personne set ville ='Lyon' where personne_id in (5,8);\r\nQuery OK, 2 rows affected (0.06 sec)\r\nRows matched: 2 Changed: 2 Warnings: 0\r\n\r\nmysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-03-27 17:07:38 | 11 | 1 | 4 |\r\n| world | ville | 2019-03-27 11:40:11 | 11 | 1 | 2 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n3 rows in set (0.00 sec)<\/pre>\n<p>Effectivement, malgr\u00e9 la modification de 5 lignes sur les 11 lignes de la table personne, les statistiques de la table personne n&#8217;ont pas \u00e9t\u00e9 mises \u00e0 jour.<\/p>\n<p>Avec la commande update, nous pouvons remettre \u00e0 jour les statistiques des histogrammes sur plusieurs colonnes de la table personne.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; analyze table personne update histogram on age, ville with 16 buckets;\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n| world.personne | histogram | status | Histogram statistics created for column 'age'. |\r\n| world.personne | histogram | status | Histogram statistics created for column 'ville'. |\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n2 rows in set (0.11 sec)<\/pre>\n<p>L&#8217;histogramme sur la colonne age va \u00eatre cr\u00e9\u00e9 et celui pour la colonne ville va \u00eatre \u00e9cras\u00e9 par le nouveau.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; SELECT schema_name, table_name, column_name, histogram-&gt;'$.&quot;number-of-buckets-specified&quot;' as number_of_buckets, histogram-&gt;'$.&quot;sampling-rate&quot;' as sampling_rate, HISTOGRAM-&gt;'$.&quot;last-updated&quot;' as last_updated\r\n-&gt; FROM INFORMATION_SCHEMA.COLUMN_STATISTICS\r\n-&gt; WHERE SCHEMA_NAME = &quot;world&quot;\r\n-&gt; AND TABLE_NAME IN ('personne','ville');\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | number_of_buckets | sampling_rate | last_updated |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| world | personne | age | 16 | 1.0 | 2019-03-28 10:46:04.115520 |\r\n| world | personne | ville | 16 | 1.0 | 2019-03-28 10:46:04.135520 |\r\n| world | ville | code_postal | 16 | 1.0 | 2019-03-28 08:46:57.299199 |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n3 rows in set (0.00 sec)<\/pre>\n<p>On peut supprimer \u00e9galement un histogramme avec un DROP histogram.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; analyze table personne drop histogram on age;\r\n+----------------+-----------+----------+------------------------------------------------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+----------------+-----------+----------+------------------------------------------------+\r\n| world.personne | histogram | status | Histogram statistics removed for column 'age'. |\r\n+----------------+-----------+----------+------------------------------------------------+\r\n1 row in set (0.09 sec)\r\n\r\nmysql&gt; SELECT schema_name, table_name, column_name, histogram-&gt;'$.&quot;number-of-buckets-specified&quot;' as number_of_buckets, histogram-&gt;'$.&quot;sampling-rate&quot;' as sampling_rate, HISTOGRAM-&gt;'$.&quot;last-updated&quot;' as last_updated\r\n-&gt; FROM INFORMATION_SCHEMA.COLUMN_STATISTICS\r\n-&gt; WHERE SCHEMA_NAME = &quot;world&quot;\r\n-&gt; AND TABLE_NAME IN ('personne','ville');\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | number_of_buckets | sampling_rate | last_updated |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| world | personne | ville | 16 | 1.0 | 2019-03-28 10:46:04.135520 |\r\n| world | ville | code_postal | 16 | 1.0 | 2019-03-28 08:46:57.299199 |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n2 rows in set (0.00 sec)<\/pre>\n<p>Pour autant, si nous cr\u00e9ons un histogramme de statistiques sur plusieurs colonnes d&#8217;une table et qu&#8217;une de ces colonnes n&#8217;existe pas, le serveur va quand m\u00eame cr\u00e9er et stocker l&#8217;histogramme pour les autres colonnes pr\u00e9sentes dans la table.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; analyze table personne update histogram on ville,age,nom,pays with 16 buckets;\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n| world.personne | histogram | status | Histogram statistics created for column 'age'. |\r\n| world.personne | histogram | status | Histogram statistics created for column 'nom'. |\r\n| world.personne | histogram | Error | The column 'pays' does not exist. |\r\n| world.personne | histogram | status | Histogram statistics created for column 'ville'. |\r\n+----------------+-----------+----------+--------------------------------------------------+\r\n4 rows in set (0.08 sec)\r\n\r\nmysql&gt; SELECT schema_name, table_name, column_name, histogram-&gt;'$.&quot;number-of-buckets-specified&quot;' as number_of_buckets, histogram-&gt;'$.&quot;sampling-rate&quot;' as sampling_rate, HISTOGRAM-&gt;'$.&quot;last-updated&quot;'\r\nas last_updated\r\n-&gt; FROM INFORMATION_SCHEMA.COLUMN_STATISTICS\r\n-&gt; WHERE SCHEMA_NAME = &quot;world&quot;\r\n-&gt; AND TABLE_NAME IN ('personne','ville');\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | number_of_buckets | sampling_rate | last_updated |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| world | personne | ville | 16 | 1.0 | 2019-03-28 14:01:41.921075 |\r\n| world | ville | code_postal | 16 | 1.0 | 2019-03-28 08:46:57.299199 |\r\n| world | personne | age | 16 | 1.0 | 2019-03-28 14:01:41.901075 |\r\n| world | personne | nom | 16 | 1.0 | 2019-03-28 14:01:41.921075 |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n4 rows in set (0.00 sec)<\/pre>\n<p>Si on r\u00e9active le recalcul automatique des statistiques si 10% de la table est modifi\u00e9 et que l&#8217;on ajoute ou que l&#8217;on met \u00e0 jour la table personne, nous pouvons voir que ces statistiques sont mises \u00e0 jour apr\u00e8s modification de 2 lignes sur ces 11.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; set global innodb_stats_auto_recalc=ON;\r\nQuery OK, 0 rows affected (0.04 sec)\r\n\r\nmysql&gt; show global variables like 'innodb_stats_auto_recalc';\r\n+--------------------------------------+-------------+\r\n| Variable_name | Value |\r\n+--------------------------------------+-------------+\r\n| innodb_stats_auto_recalc | ON |\r\n+--------------------------------------+-------------+\r\n1 rows in set (0.12 sec)\r\n\r\nmysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-03-27 17:07:38 | 11 | 1 | 4 |\r\n| world | ville | 2019-03-27 11:40:11 | 11 | 1 | 2 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n2 rows in set (0.00 sec)\r\n\r\nmysql&gt; update personne set ville='Lille' where personne_id=3;\r\nQuery OK, 1 row affected (0.05 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update personne set ville='Bordeaux' where personne_id=9;\r\nQuery OK, 1 row affected (0.07 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; update personne set ville='Montpellier' where personne_id=6;\r\nQuery OK, 1 row affected (0.10 sec)\r\nRows matched: 1 Changed: 1 Warnings: 0\r\n\r\nmysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-03-28 15:58:31 | 11 | 1 | 4 |\r\n| world | ville | 2019-03-27 11:40:11 | 11 | 1 | 2 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n2 rows in set (0.00 sec)\r\n\r\nmysql&gt; insert into personne (prenom,nom,ville,age) values ('Frank','Lamande','Nantes',44);\r\nQuery OK, 1 row affected (0.09 sec)\r\n\r\nmysql&gt; insert into personne (prenom,nom,ville,age) values ('Ripaux','David','Nantes',43);\r\nQuery OK, 1 row affected (0.06 sec)\r\n\r\nmysql&gt; insert into personne (prenom,nom,ville,age) values ('Lobreau','Benoit','Nantes',37);\r\nQuery OK, 1 row affected (0.07 sec)\r\n\r\nmysql&gt; select * from mysql.innodb_table_stats where database_name='world' and table_name in ('personne','ville');\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n| world | personne | 2019-03-28 16:04:11 | 14 | 1 | 4 |\r\n| world | ville | 2019-03-27 11:40:11 | 11 | 1 | 2 |\r\n+---------------+------------+---------------------+--------+----------------------+--------------------------+\r\n2 rows in set (0.00 sec)<\/pre>\n<p>On constate bien qu&#8217;apr\u00e8s la modification ou l&#8217;ajout de minimum 3 lignes de la table personne, les statistiques ont \u00e9t\u00e9 mises \u00e0 jour gr\u00e2ce au param\u00e8tre innodb_stats_auto_recalc.<\/p>\n<p>A partir de MySQL 8.0.2, il existe aussi une nouvelle variable syst\u00e8me <strong>histogram_generation_max_mem_size<\/strong>. Cette nouvelle variable permet de contr\u00f4ler un peu la quantit\u00e9 de m\u00e9moire que le serveur MySQL va autoriser \u00e0 utiliser pour g\u00e9n\u00e9rer les statistiques d&#8217;histogramme. La valeur par d\u00e9faut de cette variable est de 20Mo et sa valeur minimale est de 1Mo.<\/p>\n<p>Cependant, pourquoi irons-nous changer la valeur de cette variable pour les statistiques d&#8217;histogramme ?<\/p>\n<p>Quand on cr\u00e9\u00e9 un histogramme sur une colonne, le serveur MySQL va lire toutes les donn\u00e9es en m\u00e9moire et va faire le travail aussi en m\u00e9moire m\u00eame avec le tri. Pour autant, si on veut cr\u00e9er un histogramme sur de tr\u00e8s grosses tables, cela va lire des m\u00e9ga voir giga de donn\u00e9es en m\u00e9moire et ce n&#8217;est peut-\u00eatre pas ce que l&#8217;on souhaite.<\/p>\n<p>Du coup, en fonction de la m\u00e9moire spc\u00e9cifi\u00e9e par la variable histogram_generation_max_mem_size, le serveur MySQL va calculer le nombre de lignes de donn\u00e9es qui peuvent \u00eatre stock\u00e9es en m\u00e9moire. Si MySQL ne peut pas tout contenir en m\u00e9moire, il va contenir un sous-ensemble de lignes en fonction de la m\u00e9moire donn\u00e9e et utilisera un &#8220;\u00e9chantillonage&#8221;.<\/p>\n<p>Ce &#8220;taux d&#8217;\u00e9chantillonage&#8221; peut \u00eatre observ\u00e9 dans la colonne <strong>histogram<\/strong> de la table <strong>column_statistics<\/strong>.<\/p>\n<p>Avec l&#8217;exemple ci-dessous, nous allons modifier la m\u00e9moire sp\u00e9cifi\u00e9e de la variable histogram_generation_max_mem_size afin de voir les changements qui peuvent s&#8217;op\u00e9rer sur la colonne amount de la table payment pour la base sakila.<br \/>\nLa table payment de la base sakila est l&#8217;une des 2 plus grosses tables du jeu de donn\u00e9es d&#8217;exemple fourni par la version MySQL.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; show global variables like 'histogram%';\r\n+-----------------------------------+----------+\r\n| Variable_name | Value |\r\n+-----------------------------------+----------+\r\n| histogram_generation_max_mem_size | 20000000 |\r\n+-----------------------------------+----------+\r\n1 row in set, 1 warning (0.83 sec)\r\n\r\nmysql&gt; set histogram_generation_max_mem_size=1000000;\r\nQuery OK, 0 rows affected (0.09 sec)\r\n\r\nmysql&gt; show global variables like 'histogram%';\r\n+-----------------------------------+----------+\r\n| Variable_name | Value |\r\n+-----------------------------------+----------+\r\n| histogram_generation_max_mem_size | 20000000 |\r\n+-----------------------------------+----------+\r\n1 row in set, 1 warning (0.01 sec)\r\n\r\nmysql&gt; set global histogram_generation_max_mem_size=1000000;\r\nQuery OK, 0 rows affected (0.02 sec)\r\n\r\nmysql&gt; show global variables like 'histogram%';\r\n+-----------------------------------+---------+\r\n| Variable_name | Value |\r\n+-----------------------------------+---------+\r\n| histogram_generation_max_mem_size | 1000000 |\r\n+-----------------------------------+---------+\r\n1 row in set, 1 warning (0.01 sec)<\/pre>\n<p>On a modifier la variable histogram_generation_max_mem_size a sa valeur la plus petite.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">mysql&gt; SELECT schema_name, table_name, column_name, histogram-&gt;'$.&quot;number-of-buckets-specified&quot;' as number_of_buckets, histogram-&gt;'$.&quot;sampling-rate&quot;' as sampling_rate, HISTOGRAM-&gt;'$.&quot;last-updated&quot;'\r\n-&gt; as last_updated\r\n-&gt; FROM INFORMATION_SCHEMA.COLUMN_STATISTICS\r\n-&gt; WHERE SCHEMA_NAME = &quot;sakila&quot;\r\n-&gt; AND TABLE_NAME IN ('customer','payment');\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | number_of_buckets | sampling_rate | last_updated |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n| sakila | payment | rental_id | 16 | 1.0 | 2019-03-29 10:55:55.343710 |\r\n+-------------+------------+-------------+-------------------+---------------+----------------------------+\r\n1 row in set (0.00 sec)\r\n\r\nmysql&gt; analyze table sakila.payment update histogram on amount with 16 buckets;\r\n+----------------+-----------+----------+---------------------------------------------------+\r\n| Table | Op | Msg_type | Msg_text |\r\n+----------------+-----------+----------+---------------------------------------------------+\r\n| sakila.payment | histogram | status | Histogram statistics created for column 'amount'. |\r\n+----------------+-----------+----------+---------------------------------------------------+\r\n1 row in set (0.10 sec)\r\n\r\nmysql&gt; SELECT schema_name, table_name, column_name, histogram-&gt;'$.&quot;number-of-buckets-specified&quot;' as number_of_buckets, histogram-&gt;'$.&quot;sampling-rate&quot;' as sampling_rate, HISTOGRAM-&gt;'$.&quot;last-updated&quot;'\r\n-&gt; as last_updated\r\n-&gt; FROM INFORMATION_SCHEMA.COLUMN_STATISTICS\r\n-&gt; WHERE SCHEMA_NAME = &quot;sakila&quot;\r\n-&gt; AND TABLE_NAME IN ('customer','payment');\r\n+-------------+------------+-------------+-------------------+-------------------+----------------------------+\r\n| SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | number_of_buckets | sampling_rate | last_updated |\r\n+-------------+------------+-------------+-------------------+-------------------+----------------------------+\r\n| sakila | payment | rental_id | 16 | 1.0 | 2019-03-29 10:55:55.343710 |\r\n| sakila | payment | amount | 16 | 0.863414701534806 | 2019-04-01 14:44:55.735269 |\r\n+-------------+------------+-------------+-------------------+-------------------+----------------------------+\r\n2 rows in set (0.00 sec)<\/pre>\n<p>&nbsp;<\/p>\n<p>On constate que l&#8217;optimizer aura cr\u00e9\u00e9 un histogramme en lisant environ 86% des donn\u00e9es de la colonne amount de la table payment sur la base sakila.<br \/>\nCependant, l&#8217;\u00e9chantillonage n&#8217;est pas d\u00e9terministe et donc si on fait deux fois une mise \u00e0 jour de l&#8217;histogramme sur le m\u00eame jeu de donn\u00e9es, on peut avoir 2 histogrammes diff\u00e9rents si l&#8217;\u00e9chantillonage est utilis\u00e9.<\/p>\n<p>&nbsp;<\/p>\n<p>L&#8217;utilisation d&#8217;un histogramme peut \u00eatre autant int\u00e9ressante voir plus efficace qu&#8217;un index sur une colonne afin d&#8217;am\u00e9liorer une requ\u00eate.<\/p>\n<p>&nbsp;<\/p>\n<p>Vous en savez donc un peu plus maintenant sur les statistiques d&#8217;histogrammes et leur utilisation en MySQL 8.<\/p>\n<p>&nbsp;<\/p>\n<p>A tr\u00e8s vite pour de nouveaux articles sur MySQL !<\/p>\n<p>Erwan Ollitrault<\/p>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F7387&#038;text=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F7387&#038;title=Nouveaut%C3%A9s%20MySQL%208.0%20%3A%20Les%20Histogrammes\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Nouveaut%C3%A9s%20MySQL%208.0%20%3A%20Les%20Histogrammes&#038;body=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20:%20https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F7387\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/mail.png\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>Ce quatri\u00e8me article concerne les statistiques d&#8217;histogramme. Depuis la version 5.6, il est possible de cr\u00e9er des statistiques persist\u00e9s avec l&#8217;option innodb_stats_persistent=1 (par d\u00e9faut depuis la 5.6.6) ou par table avec stats_persistent=1. Les statistiques sont alors stock\u00e9es dans la colonne&hellip; <a href=\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\" class=\"more-link\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":7796,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[313,310,308,61],"class_list":["post-7387","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mysql","tag-histogrammes","tag-mysql-8-0","tag-nouveautes","tag-statistiques"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes - Capdata TECH BLOG<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes - Capdata TECH BLOG\" \/>\n<meta property=\"og:description\" content=\"Ce quatri\u00e8me article concerne les statistiques d&#8217;histogramme. Depuis la version 5.6, il est possible de cr\u00e9er des statistiques persist\u00e9s avec l&#8217;option innodb_stats_persistent=1 (par d\u00e9faut depuis la 5.6.6) ou par table avec stats_persistent=1. Les statistiques sont alors stock\u00e9es dans la colonne&hellip; Continuer la lecture &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\" \/>\n<meta property=\"og:site_name\" content=\"Capdata TECH BLOG\" \/>\n<meta property=\"article:published_time\" content=\"2019-06-25T08:34:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-09-13T09:38:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2019\/06\/My_histogrammes.png\" \/>\n\t<meta property=\"og:image:width\" content=\"629\" \/>\n\t<meta property=\"og:image:height\" content=\"421\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Capdata team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"Capdata team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"26 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\"},\"author\":{\"name\":\"Capdata team\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/person\/bfd9395c8ba4fa125792a543377035e9\"},\"headline\":\"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes\",\"datePublished\":\"2019-06-25T08:34:21+00:00\",\"dateModified\":\"2019-09-13T09:38:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\"},\"wordCount\":5235,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/blog.capdata.fr\/#organization\"},\"keywords\":[\"histogrammes\",\"mysql 8.0\",\"nouveautes\",\"statistiques\"],\"articleSection\":[\"MySQL\"],\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\",\"url\":\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\",\"name\":\"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes - Capdata TECH BLOG\",\"isPartOf\":{\"@id\":\"https:\/\/blog.capdata.fr\/#website\"},\"datePublished\":\"2019-06-25T08:34:21+00:00\",\"dateModified\":\"2019-09-13T09:38:53+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/blog.capdata.fr\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.capdata.fr\/#website\",\"url\":\"https:\/\/blog.capdata.fr\/\",\"name\":\"Capdata TECH BLOG\",\"description\":\"Le blog technique sur les bases de donn\u00e9es de CAP DATA Consulting\",\"publisher\":{\"@id\":\"https:\/\/blog.capdata.fr\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.capdata.fr\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/blog.capdata.fr\/#organization\",\"name\":\"Capdata TECH BLOG\",\"url\":\"https:\/\/blog.capdata.fr\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp\",\"contentUrl\":\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp\",\"width\":800,\"height\":254,\"caption\":\"Capdata TECH BLOG\"},\"image\":{\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/company\/cap-data-consulting\/mycompany\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/person\/bfd9395c8ba4fa125792a543377035e9\",\"name\":\"Capdata team\",\"sameAs\":[\"https:\/\/www.capdata.fr\"],\"url\":\"https:\/\/blog.capdata.fr\/index.php\/author\/admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes - Capdata TECH BLOG","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/","og_locale":"fr_FR","og_type":"article","og_title":"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes - Capdata TECH BLOG","og_description":"Ce quatri\u00e8me article concerne les statistiques d&#8217;histogramme. Depuis la version 5.6, il est possible de cr\u00e9er des statistiques persist\u00e9s avec l&#8217;option innodb_stats_persistent=1 (par d\u00e9faut depuis la 5.6.6) ou par table avec stats_persistent=1. Les statistiques sont alors stock\u00e9es dans la colonne&hellip; Continuer la lecture &rarr;","og_url":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/","og_site_name":"Capdata TECH BLOG","article_published_time":"2019-06-25T08:34:21+00:00","article_modified_time":"2019-09-13T09:38:53+00:00","og_image":[{"width":629,"height":421,"url":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2019\/06\/My_histogrammes.png","type":"image\/png"}],"author":"Capdata team","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"Capdata team","Dur\u00e9e de lecture estim\u00e9e":"26 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#article","isPartOf":{"@id":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/"},"author":{"name":"Capdata team","@id":"https:\/\/blog.capdata.fr\/#\/schema\/person\/bfd9395c8ba4fa125792a543377035e9"},"headline":"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes","datePublished":"2019-06-25T08:34:21+00:00","dateModified":"2019-09-13T09:38:53+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/"},"wordCount":5235,"commentCount":0,"publisher":{"@id":"https:\/\/blog.capdata.fr\/#organization"},"keywords":["histogrammes","mysql 8.0","nouveautes","statistiques"],"articleSection":["MySQL"],"inLanguage":"fr-FR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/","url":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/","name":"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes - Capdata TECH BLOG","isPartOf":{"@id":"https:\/\/blog.capdata.fr\/#website"},"datePublished":"2019-06-25T08:34:21+00:00","dateModified":"2019-09-13T09:38:53+00:00","breadcrumb":{"@id":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.capdata.fr\/index.php\/nouveautes-mysql-8-0-les-histogrammes\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/blog.capdata.fr\/"},{"@type":"ListItem","position":2,"name":"Nouveaut\u00e9s MySQL 8.0 : Les Histogrammes"}]},{"@type":"WebSite","@id":"https:\/\/blog.capdata.fr\/#website","url":"https:\/\/blog.capdata.fr\/","name":"Capdata TECH BLOG","description":"Le blog technique sur les bases de donn\u00e9es de CAP DATA Consulting","publisher":{"@id":"https:\/\/blog.capdata.fr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.capdata.fr\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/blog.capdata.fr\/#organization","name":"Capdata TECH BLOG","url":"https:\/\/blog.capdata.fr\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/","url":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp","contentUrl":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp","width":800,"height":254,"caption":"Capdata TECH BLOG"},"image":{"@id":"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/company\/cap-data-consulting\/mycompany\/"]},{"@type":"Person","@id":"https:\/\/blog.capdata.fr\/#\/schema\/person\/bfd9395c8ba4fa125792a543377035e9","name":"Capdata team","sameAs":["https:\/\/www.capdata.fr"],"url":"https:\/\/blog.capdata.fr\/index.php\/author\/admin\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/7387","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/comments?post=7387"}],"version-history":[{"count":40,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/7387\/revisions"}],"predecessor-version":[{"id":7645,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/7387\/revisions\/7645"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/media\/7796"}],"wp:attachment":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/media?parent=7387"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/categories?post=7387"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/tags?post=7387"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}