• GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

一、导读

MySQL 8.0.19 开始支持对InnoDB引擎表数据进行采样以生成直方图统计信息。

直方图(Histogram)是关系型数据库中提供的一种基础的统计信息,最典型的用途是估计查询谓词的选择率,以便选择优化的查询执行计划。

常见的直方图种类有:等宽直方图、等高直方图。

二、步骤

2.1 SQL语句

# 创建直方图
ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
TABLE tbl_name
UPDATE HISTOGRAM ON col_name [, col_name] ...
[WITH N BUCKETS] # 删除直方图
ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
TABLE tbl_name
DROP HISTOGRAM ON col_name [, col_name] ...

2.2 直方图案例

创建直方图,更新就是等于创建,会进行重新采样

mysql> analyze table t1 update histogram on tcol01 with 2 buckets;
+---------+-----------+----------+---------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+---------+-----------+----------+---------------------------------------------------+
| test.t1 | histogram | status | Histogram statistics created for column 'tcol01'. |
+---------+-----------+----------+---------------------------------------------------+
1 row in set (6.38 sec)

删除直方图

mysql> analyze table t1 drop histogram on tcol01;
+---------+-----------+----------+---------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+---------+-----------+----------+---------------------------------------------------+
| test.t1 | histogram | status | Histogram statistics removed for column 'tcol01'. |
+---------+-----------+----------+---------------------------------------------------+
1 row in set (0.02 sec)

2.3 查看直方图统计信息

查看直方图的视图信息

mysql> show create table information_schema.column_statistics\G
*************************** 1. row ***************************
View: COLUMN_STATISTICS
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`COLUMN_STATISTICS` AS select `mysql`.`column_statistics`.`schema_name` AS `SCHEMA_NAME`,`mysql`.`column_statistics`.`table_name` AS `TABLE_NAME`,`mysql`.`column_statistics`.`column_name` AS `COLUMN_NAME`,`mysql`.`column_statistics`.`histogram` AS `HISTOGRAM` from `mysql`.`column_statistics` where (0 <> can_access_table(`mysql`.`column_statistics`.`schema_name`,`mysql`.`column_statistics`.`table_name`))
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.01 sec)

可以通过 information_schema.column_statistics 查看,会列出所有直方图信息

mysql> select * from information_schema.column_statistics\G;
*************************** 1. row ***************************
SCHEMA_NAME: test
TABLE_NAME: t_user
COLUMN_NAME: age
HISTOGRAM: {"buckets": [[1, 0.00002000013333422223], [10, 0.23445489636597577], [11, 0.46630977539850266], [12, 0.5326868845792305], [13, 0.5991973279821865], [14, 0.665747771651811], [15, 0.7325715504770032], [16, 0.7999486663244422], [17, 0.8668091120607471], [18, 0.9329928866192441], [19, 0.9999766665111101], [127, 1.0]], "data-type": "int", "null-values": 0.0, "collation-id": 8, "last-updated": "2022-04-21 06:53:35.194420", "sampling-rate": 1.0, "histogram-type": "singleton", "number-of-buckets-specified": 100}
......

2.3 直方图分类

对于等宽直方图,每个桶包含两个值,大致信息如下

SCHEMA_NAME: test  # 库名
TABLE_NAME: t1 # 表名
COLUMN_NAME: tcol01 # 列名
HISTOGRAM: {
"buckets":[
[
0, # 1.桶的值,表中实际数据的取值。类型是取决于字段数据类型,比如下面是`int`类型。
0.06585605673110825 # 2.取值频率,桶的值出现的大致频率,double类型。
],
......
],
"data-type":"int", # 数据类型
"null-values":0, # 是否有NULL值
"collation-id":8,
"last-updated":"2022-04-21 06:59:55.850333", # 桶最后更新时间,不会自动更新
"sampling-rate":0.4059331843720921, # 采样率,如果是1,表示采集所有数据
"histogram-type":"singleton", # 桶类型,等宽
"number-of-buckets-specified":100 # 桶数量
}

对于等高直方图,每个桶中包含四个值,大致信息如下

SCHEMA_NAME: test
TABLE_NAME: t1
COLUMN_NAME: tcol10
HISTOGRAM: {
"buckets":[
[
"2021-04-18 12:12:00.000000", # 1.最小值
"2021-04-22 05:05:56.000000", # 2.最大值
0.010002279268725782, # 3.桶的值出现的大致频率,double类型
3523 # 4.桶值出现的次数
],
......
],
"data-type":"datetime",
"null-values":0,
"collation-id":8,
"last-updated":"2022-04-21 07:00:43.232745",
"sampling-rate":0.18943548604030958,
"histogram-type":"equi-height", # 桶类型,等高
"number-of-buckets-specified":100
}

2.4 使用限制

直方图是对表进行操作,可以看下不同的表类型对直方图的支持情况:

  • 1、直方图支持 InnoDB,NDB,MyISAM 表类型,支持分区表类型,不支持 views 类型。
  • 2、加密表不支持创建,主要还是为了避免相关数据泄漏。
  • 3、临时表不支持创建,连接会话关闭后,临时表就被清理了,也就没有创建必要。
  • 4、单列唯一索引、主键索引不支持创建直方图,创建的时候会提示Error,并输出错误提示The column 'id' is covered by a single-part unique index.
  • 5、几何类型(空间数据)和JSON类型也暂时不支持直方图。

直方图采集的基本单位是表中的列数据,也就是当列数据或类型发生变更或删除的时候直方图可能也会出现相应变化,经过测试有如下情况:

  • 1、当表被删除的时候,直方图会同步被删除,truncte操作不会有影响,同理insert、delete、update也不会有影响
  • 2、当修改字段类型、字段长度,直方图会被删除。
  • 3、当修改表名后,直方图TABLE_NAME字段会同步更新,和新表建立关联。
  • 4、修改字段字符集后,直方图会被删除。例如ALTER TABLE t1006 MODIFY utf8 VARCHAR(64) CHARACTER SET latin1;

其他注意点:

  • 1、ANALYZE TABLE 分析过程需要从表定义缓存中删除表,所以该过程会产生一个flush锁。如果有长时间运行的语句或事务仍在使用表,则后续语句和事务必须等待这些操作完成后才释放flush锁

  • 2、直方图把统计数据存储在数据字典的的统计表内,所以当innodb_read_only参数开启的时候,可能由于无法更新数据字典t统计信息导致执行失败,

三、直方图使用案例

先查看下t_userage各个年龄段的人数;当前t_userage字段没有建立索引。

mysql> select age,count(id) from t_user group by age;
+------+-----------+
| age | count(id) |
+------+-----------+
| 11 | 69556 |
| 1 | 6 |
| 127 | 7 |
| 10 | 70330 |
| 19 | 20095 |
| 13 | 19953 |
| 18 | 19855 |
| 12 | 19913 |
| 14 | 19965 |
| 17 | 20058 |
| 15 | 20047 |
| 16 | 20213 |
+------+-----------+
12 rows in set (0.18 sec)

解析查询年龄段 > 10 age < 12

通过分析,可以看出执行过程type=ALL走了全表扫描,filtered=11.11 过滤比例还是比较低的,同时表上没有建立索引,所以key=NuLL

mysql> explain select * from t_user where age>10 and age<12;
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | t_user | NULL | ALL | NULL | NULL | NULL | NULL | 299131 | 11.11 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

创建一个直方图;根据步骤1查出来,年龄段大概分类12,所以我们建立12个桶

mysql> analyze table t_user update histogram on age with 12 buckets;
+-------------+-----------+----------+------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+-------------+-----------+----------+------------------------------------------------+
| test.t_user | histogram | status | Histogram statistics created for column 'age'. |
+-------------+-----------+----------+------------------------------------------------+
1 row in set (0.06 sec) # 查看建立的直方图信息
mysql> select * from information_schema.column_statistics\G;
SCHEMA_NAME: test
TABLE_NAME: t_user
COLUMN_NAME: age
HISTOGRAM: {{
"buckets": [
[1, 0.0002608242044861763],
[10, 0.27339593114241006],
[11, 0.5397496087636933],
[12, 0.5968179447052686],
[13, 0.6553990610328638],
[14, 0.7131977047470005],
[15, 0.7706311945748565],
[16, 0.8261345852895148],
[17, 0.8855503390714657],
[18, 0.9423056859676577],
[19, 0.9996870109546165],
[127, 1.0]
],
"data-type": "int",
"null-values": 0.0,
"collation-id": 8,
"last-updated": "2022-04-24 03:00:47.361704",
"sampling-rate": 0.059696731054764834,
"histogram-type": "singleton",
"number-of-buckets-specified": 12
}
3 rows in set (0.00 sec)

再进行查询分析

通过分析,可以看出执行过程type=ALL在建立直方图后也是走了全表扫描,filtered=39.22 过滤有显著提升。

mysql> explain select * from t_user where age>10 and age<12;
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | t_user | NULL | ALL | NULL | NULL | NULL | NULL | 299131 | 39.22 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

总体而言,从两次执行计划的差别可以看出建立直方图后,filtered 列 39.22 比 没有建立直方图 11.11 值有更好的过滤效果。

PS:关于filtered列,这个字段表示存储引擎返回的数据在Server层过滤后,剩下多少满足查询的记录数量的比例。

进一步通过开启TRACE查看执行计划

由于优化器会默认的认为各个年龄段的数据分布是均匀的,所以当没有直方图扫描的范围会比较大,相应的在Server层过滤的数据也就较少。

同理,在有直方图的情况下,优化器可以通过直方图来分析年龄段的数据分布,从而调整扫描范围,过滤更多数据。

mysql> SET OPTIMIZER_TRACE = "enabled=on";
mysql> SET OPTIMIZER_TRACE_MAX_MEM_SIZE = 1000000;
mysql> explain select * from t_user where age>10 and age<12;
mysql> SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE\G; # 可以看到执行计划里面用到了`histogram_selectivity`
"considered_execution_plans": [
{
"plan_prefix": [
],
"table": "`t_user`",
"best_access_path": {
"considered_access_paths": [
{
"rows_to_scan": 299131,
"filtering_effect": [
{
"condition": "(`t_user`.`age` > 10)",
"histogram_selectivity": 0.726604
},
{
"condition": "(`t_user`.`age` < 12)",
"histogram_selectivity": 0.53975
}
],
"final_filtering_effect": 0.392184,
"access_type": "scan",
"resulting_rows": 117314,
"cost": 30193.9,
"chosen": true
}
]

四、直方图资源消耗

生成直方图需要对数据进行采样分析,这个过程需要消耗一定的内存资源和IO资源。

我们可以通过监控来查看下该过程需要消耗多少资源,当然我们也可以通过sys.x$memory_by_thread_by_current_bytes视图来对比采样前后内存的差值变化来大致预估直方图创建过程需要消耗多少内存,详细步骤可移步老叶茶馆阅读 https://mp.weixin.qq.com/s/7FI87f6t3UvbE9GGhw8iVA

另外可以通过调整参数 set session histogram_generation_max_mem_size = 1000000; 来限制内存的使用,同时这样也会相应降低采样率

五、总结

本文对直方图的内容进行简单的介绍,篇幅所限,更多细节内容请移步官网进行查看,另外关于列中已经有索引的情况下,优化器会如何选择执行计划,篇幅所限,以后再进行测试。

  • https://dev.mysql.com/doc/refman/8.0/en/analyze-table.html#analyze-table-histogram-statistics-analysis
  • https://dev.mysql.com/doc/refman/8.0/en/optimizer-statistics.html
  • https://mp.weixin.qq.com/s/7FI87f6t3UvbE9GGhw8iVA

Enjoy GreatSQL

文章推荐:

面向金融级应用的GreatSQL正式开源

https://mp.weixin.qq.com/s/cI_wPKQJuXItVWpOx_yNTg

Changes in GreatSQL 8.0.25 (2021-8-18)

https://mp.weixin.qq.com/s/qcn0lmsMoLtaGO9hbpnhVg

MGR及GreatSQL资源汇总

https://mp.weixin.qq.com/s/qXMct_pOVN5FGoLsXSD0MA

GreatSQL MGR FAQ

https://mp.weixin.qq.com/s/J6wkUpGXw3YkyEUJXiZ9xA

在Linux下源码编译安装GreatSQL/MySQL

https://mp.weixin.qq.com/s/WZZOWKqSaGSy-mpD2GdNcA

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

Gitee:

https://gitee.com/GreatSQL/GreatSQL

GitHub:

https://github.com/GreatSQL/GreatSQL

Bilibili:

https://space.bilibili.com/1363850082/video

微信&QQ群:

可搜索添加GreatSQL社区助手微信好友,发送验证信息“加群”加入GreatSQL/MGR交流微信群

QQ群:533341697

微信小助手:wanlidbc

本文由博客一文多发平台 OpenWrite 发布!

4.直方图介绍和使用|MySQL索引学习的更多相关文章

  1. Mysql索引学习笔记

    1.btree索引与hash索引 下列范围查询适用于 btree索引和hash索引: SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,2 ...

  2. MySQL索引学习记录

    参考资料: http://blog.csdn.net/v_july_v/article/details/6530142http://blog.codinglabs.org/articles/theor ...

  3. mysql 索引学习--多条件等值查询,顺序不同也能应用联合索引啦

    以前学习这一块的时候,是说:假设建立了联合索引a+b,那么查询语句也一定要是这个顺序才能应用该索引. 那么实际是怎样呢,经过mysql这么多次版本升级,相信mysql已经给我们做了某些优化. 下面是我 ...

  4. 3.联合索引、覆盖索引及最左匹配原则|MySQL索引学习

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 在数据检索的过程中,经常会有多个列的匹配需求,今天介绍下联合索引的使用以及最左匹配原则的案例. 最左匹配原则作用在联 ...

  5. ”MySQL索引“学习总结

    序 learn by doing 是最快的学习方式.在百度外卖研发中心,我每天工作接触数据库方面最多的就是"索引",另外面试官在面试时也一定会考察到索引. Part 1, Expl ...

  6. mysql索引学习

    索引用于快速找出在某列中有一特定值的行. 如果不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行. 表越大,查询数据所花费的时间越多. 如果表中查询的列有一个索引,MySQL能快速 ...

  7. mysql索引学习----2----创建索引、修改索引、删除索引的命令语句

    查看表中已经存在 index:show index from table_name; 创建和删除索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER ...

  8. MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项

    以下的文章主要介绍的是MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项是值得我们大家注意的,我们大家可能不知道过多的对索引进行使用将会造成滥用.因此MySQL索引也会有它的缺点: 虽然索引 ...

  9. MySQL 索引与查询优化

    本文介绍一些优化 MySQL 索引设计和查询的建议.在进行优化工作前,请务必了解MySQL EXPLAIN命令: 查看执行计划 索引 索引在逻辑上是指从索引列(关键字)到数据的映射,通过索引可以快速的 ...

随机推荐

  1. Springboot启动类及注解说明

    Spring boot的启动是基于main方法的,其主要注解为: 1. @springBootApplication:项目的启动注解,是一个组合注解,包含@SpringbootConfiguratio ...

  2. 859. Buddy Strings - LeetCode

    Question 859. Buddy Strings Solution 题目大意: 两个字符串,其中一个字符串任意两个字符互换后与另一个字符串相等,只能互换一次 思路: diff 记录不同字符数 两 ...

  3. 安装Zabbix到Ubuntu(APT)

    运行环境 系统版本:Ubuntu 16.04.2 LTS 软件版本:Zabbix-4.0.2 硬件要求:无 安装过程 1.安装APT-Zabbix存储库 APT-Zabbix存储库由Zabbix官网提 ...

  4. 关于我学git这档子事(5)

    对于错误: fatal: refusing to merge unrelated histories 解决之道: git pull origin main --allow-unrelated-hist ...

  5. 【Azure 存储服务】Java Azure Storage SDK V12使用Endpoint连接Blob Service遇见 The Azure Storage endpoint url is malformed

    问题描述 使用Azure Storage Account的共享访问签名(Share Access Signature) 生成的终结点,连接时遇见  The Azure Storage endpoint ...

  6. 测试软件稳定性、健壮性之Monkey工具--简洁与深入

    搭建环境这章节没做详细说明,因为我是前期做APP自动化是已经将 SDK 以及JDK给安装配置好了,这次是直接上来演示monkey的功能点以及运用 一.什么是稳定性测试? 通过随机点击屏幕一段时间,看看 ...

  7. php原生PHPExcel插件导表(附表格合并,加粗居中及加边框换行操作)

    PHPExcel是用来操作Office Excel文档的一个PHP类库,它基于微软的OpenXML标准和PHP语言.可以使用它来读取.写入不同格式的电子表格,如 Excel(BIFF) .xls, E ...

  8. 开发工具-RSA加解密

    更新日志 2022年6月10日 初始化链接. https://toolb.cn/rsa

  9. go-zero微服务实战系列(四、CRUD热热身)

    上一篇文章我们把整个项目的架子搭建完成,服务在本地也已经能运行起来了,顺利成章的接下来我们就应该开始写业务逻辑代码了,但是单纯的写业务逻辑代码是比较枯燥的,业务逻辑的代码我会不断地补充到 lerbon ...

  10. Python:socket编程教程

    ocket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个py文件,一个服务端,一个客户端. 首先,导入Python中的socket模块: import socket Pytho ...