当前位置: 首页 > news >正文

mysql 列合并_第14期:数据页合并

feb3feeca346ed5a4ef3d47f9bf3292a.png MySQL InnoDB 表数据页或者二级索引页(简称数据页或者索引页)的合并与分裂对 InnoDB 表整体性能影响很大;数据页的这类操作越多,对 InnoDB 表数据写入的影响越大。 MySQL 提供了一个数据页合并临界值(MERGE_THRESHOLD),在某些场景下,可以人为介入,减少数据页的合并与分裂。 在 InnoDB 表里,每个数据页默认16K 大小,默认 MERGE_THRESHOLD 值为 50,取值范围从 1 到 50,默认值即是最大值。也就是当页面记录数占比小于 50% 时,MySQL 会把这页和相邻的页面进行合并,保证数据页的紧凑,避免太多浪费。 触发临界值场景 场景一: 页 A 里本来数据占用 100%,有一部分记录被删掉后,数据占用小于 50%,刚好触发了临界值。

场景二:

页 B 里存放的记录被更新为更短的形式,比如记录值由 rpad('我爱你们所有人' , 10000, '添加冗余字符')变为 '我只爱你' ,这时候记录对数据页占用也小于 50%,刚好触发了临界值。 简述数据页的合并 页 A 在删除一些记录后,此页里剩余记录对页 A 的占用小于 MERGE_THRESHOLD 设定的值,此时刚好页 A 相邻的一个页 C,数据占用也不到 50%,这时候 MySQL 会把页 C 的记录并入页 A,之后页 C 的空间就被释放,不包含任何数据,页 C 就可用于以后新记录的写入,避免空间的浪费。  简述数据页的分裂
  • 页 D 和页 E,两个页面记录占用都在 49%。那么页合并后,页 D 记录占用 98%,只剩下 2%。

  • 页 F 和页 H,两个页面记录占用也都是 49%,那么合并后,页 F 记录占用 98%,也只剩下 2%。

此时有新的插入请求过来,这条记录的主键刚好在页 D 和页 F 之间,可是页 D 和页 F 都只剩下 2% 的空间,不够插入这条记录。那怎么办?此时只能拆分页 D。建立一个新的页 I,完了把页 D 原来的记录和新插入的记录做一个排序,再按照新的顺序把页 D 填满,剩下的数据放到页 I。所以页分裂会涉及到老页数据的迁移到新建页的建立,如果页的分裂频繁,那开销很大。  下来看看 MERGE_THRESHOLD 的实际用法与监测。 注意!MERGE_THRESHOLD 不能小写,必须大写!小写就会被 MySQL 当作简单的注释。

1. 表的 MERGE_THRESHOLD

对整张表设置 MERGE_THRESHOLD,需要把这个值放入表的 comment 中。INNODB 并不是第一个在表注释里定义对表数据控制选项的, MySQL 之前的列式引擎 brighthouse 早这么干过,把对表的一些利于优化的 HINT 放入到 comment 里。具体的语法为:
mysql> create table sample1(id int primary key,r1 int, r2 varchar(1000)) comment 'MERGE_THRESHOLD=40';Query OK, 0 rows affected (0.08 sec)
或者是针对之前的表更改 MERGE_THRESHOLD 值
mysql> alter table t1 comment 'MERGE_THRESHOLD=40';Query OK, 0 rows affected (0.02 sec)Records: 0  Duplicates: 0  Warnings: 0

2. 索引的 MERGE_THRESHOLD

也可以针对单个索引列设置 MERGE_THRESHOLD 值,单个列的 MERGE_THRESHOLD 优先级比表高,也就是会覆盖掉表的设置。
mysql> create table t1(id int, key idx_id(id) comment 'MERGE_THRESHOLD=40');Query OK, 0 rows affected (0.08 sec)
或者先删除索引,再建立新的。
mysql> alter table t1 drop key idx_id, add key idx_id(id) comment 'MERGE_THRESHOLD=40';Query OK, 0 rows affected (0.02 sec)Records: 0  Duplicates: 0  Warnings: 0
或者,
mysql> create index idx_id on t1(id) comment 'MERGE_THRESHOLD=40';Query OK, 0 rows affected (0.05 sec)Records: 0  Duplicates: 0  Warnings: 0

3. 查看 MERGE_THRESHOLD

可以通过查看表定义信息,
mysql> show create table sample1\G...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MERGE_THRESHOLD=40'1 row in set (0.00 sec)
可以通过单独查看索引定义信息,
mysql> show index from t1\G...     Comment:Index_comment: MERGE_THRESHOLD=401 row in set (0.00 sec)
或者可以通过 数据字典表 information_schema.innodb_indexes 来获取表里所有对象的 MERGE_THRESHOLD 值设定。  
mysql> select a.name as tablename,b.name as index_name, b.MERGE_THRESHOLD from innodb_tables as a,innodb_indexes as b where a.table_id = b.table_id and a.name like 'ytt%';+-------------+-----------------+-----------------+| tablename   | index_name      | MERGE_THRESHOLD |+-------------+-----------------+-----------------+| ytt/sample1 | PRIMARY         |              40 || ytt/t1      | GEN_CLUST_INDEX |              50 || ytt/t1      | idx_id          |              40 |+-------------+-----------------+-----------------+3 rows in set (0.00 sec)

4. MERGE_THRESHOLD 设置效果评估

innodb_metrics 表提供了两个计数器来跟踪页合并(Innodb_metrics 表非常有用,后期单独开篇详细来介绍。) 这两个计数器默认是屏蔽的,需要显式开启,
mysql> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS   -> WHERE NAME like '%index_page_merge%';+-----------------------------+----------------------------------------+| NAME                        | COMMENT                                |+-----------------------------+----------------------------------------+| index_page_merge_attempts   | Number of index page merge attempts    || index_page_merge_successful | Number of successful index page merges |+-----------------------------+----------------------------------------+2 rows in set (0.00 sec)
开启这两个计数器,
mysql> set global innodb_monitor_enable='index_page_merge_attempts';Query OK, 0 rows affected (0.00 sec)mysql> set global innodb_monitor_enableQuery OK, 0 rows affected (0.00 sec)
建立两张表,MERGE_THRESHOLD 分别为默认值和 20,导入同样的 10000 条记录,看看页面合并的对比。
mysql> create table t1_max(id int primary key,r1 int, key  idx_r1 (r1));Query OK, 0 rows affected (0.08 sec)mysql> create table t1_min(id int, primary key (id) comment 'MERGE_THRESHOLDQuery OK, 0 rows affected (0.08 sec)
对比前,先清空计数器;禁止后;重置计数器。
mysql> set global innodb_monitor_disable='index_page_merge_attempts';Query OK, 0 rows affected (0.00 sec)mysql> set global innodb_monitor_disableQuery OK, 0 rows affected (0.00 sec)mysql> set global innodb_monitor_reset_allQuery OK, 0 rows affected (0.00 sec)mysql> set global innodb_monitor_enableQuery OK, 0 rows affected (0.00 sec)
先往表 t1_max 里随机插入 1000 条记录。
replace into t1_max select ceil(rand()*1000),ceil(rand()*100) ;...mysql> select count(*) from t1_max+----------+| count(*) |+----------+|     1000 |+----------+1 row in set (0.03 sec)
再删掉 500 条记录
mysql> delete from t1_max limit 500;Query OK, 500 rows affected (0.05 sec)
查看计数器结果,尝试合并 707 次,合并成功 20 次。
mysql> SELECT name,count,max_count,avg_count  FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME like '%index_page_merge%';+-----------------------------+-------+-----------+--------------------+| name                        | count | max_count | avg_count          |+-----------------------------+-------+-----------+--------------------+|| index_page_merge_successful |    20 |        20 |  0.072992700729927 |+-----------------------------+-------+-----------+--------------------+2 rows in set (0.00 sec)
再清空计数器,对表 t1_min 执行同样的操作,
mysql> select count(*) from t1_min;+----------+| count(*) |+----------+|      500 |+----------+1 row in set (0.02 sec)mysql> delete from t1_min limit 500Query OK, 500 rows affected (0.02 sec)
再次查看计数器,尝试合并 30 次,实际成功次数仅仅为 2。比默认的合并次数少了 20 多倍。所以可以看到,在一定的数据模型下,手动控制合并临界值对数据页的合并频率调节非常有效。
mysql> SELECT name,count,max_count,avg_count  FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME like '%index_page_merge%';+-----------------------------+-------+-----------+---------------------+| name                        | count | max_count | avg_count           |+-----------------------------+-------+-----------+---------------------+|| index_page_merge_successful |     2 |         2 | 0.03333333333333333 |+-----------------------------+-------+-----------+---------------------+2 rows in set (0.00 sec)
当然,设置成最小值 1,基本上不会合并了,结果应该如下。
mysql> SELECT name,count,max_count,avg_count  FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME like '%index_page_merge%';+-----------------------------+-------+-----------+-----------+| name                        | count | max_count | avg_count |+-----------------------------+-------+-----------+-----------+|| index_page_merge_successful |     0 |      NULL |         0 |+-----------------------------+-------+-----------+-----------+2 rows in set (0.00 sec)
总结

这篇我介绍了 MySQL 索引页合并临界值的概念以及如何在实际环境中评估这个值对索引页合并以及拆分的影响,有问题或者相关建议欢迎指正回复。


文章推荐:

第11期:压缩表第12期:压缩表性能监测

第13期:表统计信息的计算


关于 MySQL 的技术内容,你们还有什么想知道的吗?赶紧 留言告诉小编吧!

39a52ffc9a8eaf4debd3bac0c33b0716.png

本文关键字:#innodb# #索引页#  想看更多技术好文,点个 “在看” 吧!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • ASP.NET之父Scott Guthrie,1月13日做客微软北京.NET俱乐部
  • mysql 统计_分享一个实用的mysql数据库表概要信息统计sql,值得收藏
  • Compile qt-2.3.10
  • python中readlines()_在Python中,read()或readlines()更快吗?
  • 递归下降分析程序的设计与实现_算法讲解之递归算法
  • zedgraph 两点之间值_高考必刷题3:计算纬线上两点间的距离
  • 大褂还是内裤
  • wpf datagrid 如何获取当前点击行_「Spire.PDF教程」如何复制 PDF 文档
  • 网络术语还在困扰你吗?
  • python做视觉识别机械手_DIY一个基于树莓派和Python的无人机视觉跟踪系统(转)...
  • 网管之路在何方
  • 判断两个list集合里的对象某个属性值是否一样_BAT面试题——22个集合框架(完)...
  • 在Linux上使用Qt编译WebKit
  • python 进度条_Python 如何实时显示进度条?
  • Massive Customization
  • django开发-定时任务的使用
  • Flex布局到底解决了什么问题
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Java知识点总结(JavaIO-打印流)
  • Mithril.js 入门介绍
  • mongo索引构建
  • ReactNativeweexDeviceOne对比
  • React系列之 Redux 架构模式
  • vue.js框架原理浅析
  • 对象引论
  • 给初学者:JavaScript 中数组操作注意点
  • 记一次删除Git记录中的大文件的过程
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 配置 PM2 实现代码自动发布
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 如何进阶一名有竞争力的程序员?
  • 探索 JS 中的模块化
  • 原生js练习题---第五课
  • C# - 为值类型重定义相等性
  • 阿里云重庆大学大数据训练营落地分享
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (5)STL算法之复制
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (k8s)Kubernetes本地存储接入
  • (Matlab)使用竞争神经网络实现数据聚类
  • (pytorch进阶之路)扩散概率模型
  • (八十八)VFL语言初步 - 实现布局
  • (蓝桥杯每日一题)love
  • (一)基于IDEA的JAVA基础1
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转)项目管理杂谈-我所期望的新人
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • .net core使用EPPlus设置Excel的页眉和页脚
  • .net 程序发生了一个不可捕获的异常
  • .NET构架之我见
  • .NET企业级应用架构设计系列之结尾篇