Worklog:  http://dev.mysql.com/worklog/task/?id=6747

git show 3f4abb52fbfe9118fc94a4b60876c16e5aa2e0e0

Make InnoDB fill factor settable (WL#6747) : This work by Yasufumi Kinoshita makes themerge_threshold settable per index. Until now it has been fixed at 50%. If the  amount of data within the page falls below the merge_threshold, e.g. when deleting a row or shortening it via an update, InnoDB will attempt to merge it with a neighbor page. This offers a way to decrease InnoDB’s overall disk footprint, at the expense of some additional work due to the additional page merges.

在该worklog中,将原先的hard code的宏定义BTR_CUR_PAGE_COMPRESS_LIMIT变成可配置的。这个宏有什么作用呢 ? 从它的注释可以看的很清楚:

/** In the pessimistic delete, if the page data size drops below this
limit, merging it to a neighbor is tried */

在做悲观删除时,当page内的数据量低于一定的比例时,会尝试合并左右兄弟节点,以节约空间。当前这个值是PAGE的一半(默认8kb),这意味着即使合并成功了,也可能因为合并后的page太满,导致随后出现Page分裂。我们可以调低这个百分比因子来减少page 合并,避免过多的分裂。用一定的空间损失来换取性能的提升。

如何使用:

在CREATE/ALTER TABLE时可以针对表级、索引级指定Merge_threshold,例如:

create table t1 (a int , b int , c int ,

primary key (a) comment ‘MERGE_THRESHOLD=45′,

key(b,c) comment ‘MERGE_THRESHOLD=48′) COMMENT ‘MERGE_THRESHOLD=42′;

alter table t1 add key (c);

root@zwx 11:56:51>SELECT NAME, MERGE_THRESHOLD FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE MERGE_THRESHOLD != 50 AND TABLE_ID = 1275;
+———+—————–+
| NAME    | MERGE_THRESHOLD |
+———+—————–+
| PRIMARY |              45 |
| b       |              48 |
| c       |              42 |
+———+—————–+

使用COMMENT来设定merge threshold, 新建的索引默认继承表级设置,除非显式指定。更具体的参考官方文档:

http://dev.mysql.com/doc/refman/5.7/en/index-page-merge-threshold.html

 

内部实现

1.定义及存储

因为定义merge threshold被包含到索引或表的comment中,语法本身未作改动,server层无需变更。

InnoDB在创建/ALTER时会去解析comment, 以创建表为例:

ha_create —> ha_innobase::create —>create_table_info_t::create_table_update_dict —> innobase_parse_hint_from_comment

innobase_parse_hint_from_comment是新增的主函数,用于解析comment中的hint:

//解析表级comment及每个索引的comment,函数innobase_parse_merge_threshold,其实就是简单的strstr函数定位到MERGE_THRESHOLD=,再进行整型转换(atoi)

//更新SYS_INDEX系统表

GEN_CLUST_INDEX(无唯一键或主键时)总是使用表级定义的merge threshold

dict_index_set_merge_threshold:在sys_index中更新每个索引的merge threshold字段

更新dict_index_t::merge_threshold

 

2.使用

将原先的hardcode替换成使用索引对象上的dict_index_t::merge_threshold

参考函数:

btr_cur_will_modify_tree,该函数用于决定修改记录是否可能导致索引树修改

btr_cur_compress_recommendation, //检查是否可以合并索引页

btr_cur_can_delete_without_compress  //删除记录时

page_delete_rec  //删除记录时

3.加载

在索引加入内内存时,会从SYS_INDEX系统表中读取索引信息,

参考函数:dict_load_index_low

展示:

修改I_S表INNODB_SYS_INDEXES,增加新列来展示索引上的threshold

兼容性

由于系统表SYS_INDEXES表发生了变化,原地升级后的新版本如果不做upgrade,表的定义也需要向前兼容,因此容忍该表缺少merge threshold列。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐