4.直方图介绍和使用|MySQL索引学习
- 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_user
上age
各个年龄段的人数;当前t_user
上age
字段没有建立索引。
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索引学习的更多相关文章
- Mysql索引学习笔记
1.btree索引与hash索引 下列范围查询适用于 btree索引和hash索引: SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,2 ...
- MySQL索引学习记录
参考资料: http://blog.csdn.net/v_july_v/article/details/6530142http://blog.codinglabs.org/articles/theor ...
- mysql 索引学习--多条件等值查询,顺序不同也能应用联合索引啦
以前学习这一块的时候,是说:假设建立了联合索引a+b,那么查询语句也一定要是这个顺序才能应用该索引. 那么实际是怎样呢,经过mysql这么多次版本升级,相信mysql已经给我们做了某些优化. 下面是我 ...
- 3.联合索引、覆盖索引及最左匹配原则|MySQL索引学习
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 在数据检索的过程中,经常会有多个列的匹配需求,今天介绍下联合索引的使用以及最左匹配原则的案例. 最左匹配原则作用在联 ...
- ”MySQL索引“学习总结
序 learn by doing 是最快的学习方式.在百度外卖研发中心,我每天工作接触数据库方面最多的就是"索引",另外面试官在面试时也一定会考察到索引. Part 1, Expl ...
- mysql索引学习
索引用于快速找出在某列中有一特定值的行. 如果不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行. 表越大,查询数据所花费的时间越多. 如果表中查询的列有一个索引,MySQL能快速 ...
- mysql索引学习----2----创建索引、修改索引、删除索引的命令语句
查看表中已经存在 index:show index from table_name; 创建和删除索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER ...
- MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项
以下的文章主要介绍的是MySQL索引的缺点以及MySQL索引在实际操作中有哪些事项是值得我们大家注意的,我们大家可能不知道过多的对索引进行使用将会造成滥用.因此MySQL索引也会有它的缺点: 虽然索引 ...
- MySQL 索引与查询优化
本文介绍一些优化 MySQL 索引设计和查询的建议.在进行优化工作前,请务必了解MySQL EXPLAIN命令: 查看执行计划 索引 索引在逻辑上是指从索引列(关键字)到数据的映射,通过索引可以快速的 ...
随机推荐
- 大数据分析——sklearn模块安装
前提条件:numpy.scipy以及matplotlib库的安装 (注:所有操作都在pycharm命令终端进行) ①numpy安装 pip install numpy ②scipy安装 pip ins ...
- 2020级cpp机考模拟题A卷-#题解2
这部分的题目都有一定难度,有兴趣的同学可以钻研一下. 特此感谢来自BDT20030 tql的支持. 2:素数的和-2 题意: 计算不大于m的素数之和.(多么容易理解的题目啊,对吧) 题解(有点复杂的 ...
- Redis快速度特性及为什么支持多线程及应用场景
转载请注明出处: 目录 1.Redis 访问速度快特性 2.Redis 6.0 为什么支持多线程? 3.Redis可以做什么 3.1.缓存 3.2.排行榜系统 3.3.计数器应用 3.4.社交网络 3 ...
- 第06组Alpha冲刺(6/6)
目录 1.1 基本情况 1.2 冲刺概况汇报 1.郝雷明 2.曹兰英 3. 方梓涵 4.曾丽莉 5.鲍凌函 6.杜筱 7.黄少丹 8.詹鑫冰 9.董翔云 10.吴沅静 1.3 冲刺成果展示 1.1 基 ...
- [第18届 科大讯飞杯 J] 能到达吗
能到达吗 题目链接:牛客5278 J 能到达吗 Description 给定一个 \(n\times m\) 的地图,地图的左上角为 \((1, 1)\) ,右下角为 \((n,m)\). 地图上有 ...
- 【Linux系列】-Linux中用shell脚本从SFTP服务器下载文件
银企直连的电子回单接口中,部分银行使用sftp服务作为文件服务器,通常只保留N天的文件内容,企业未在规定的时间范围下载文件之后就不能下载了,那么有一个自动下载的脚本岂不美滋滋. Linux安装SFTP ...
- ssh打通
打通ssh https://www.cnblogs.com/yolanda-lee/p/4975453.html
- sharepoint 配置失败,已引发类型为System.ArgumentException的异常。其他异常信息:domainName参数不支持指定的值。
解决方法:在域控制器中加入sharepoint计算机,设置为administrators组中
- Linux shell 2>&1的意思
在脚本里经常看到 ./xxx.sh > /dev/null 2>&1 ./xxx.sh > log.file 2>&1 在shell中输入输出都有对应的文件描述 ...
- linux安装源码包指定安装目录
当下载完一个源码包并且解压后 文件夹下会有一个重要的文件configure configure 文件是一个可执行的脚本文件,它将检查目标系统的配置和可用功能,比如一些检查依赖或者启用禁用一些模块,它有 ...