InnoDB索引允许NULL对性能有影响吗(3)

简介: InnoDB索引允许NULL对性能有影响吗

2. 问题2:辅助索引需要MVCC多版本读的时候,为什么需要依赖聚集索引

InnoDB的MVCC是通过在聚集索引页中同时存储了DB_TRX_ID和DB_ROLL_PTR来实现的。

但是我们从上面page dump出来的结果也很明显能看到,附注索引页是不存储DB_TRX_ID信息的。

所以说,辅助索引上如果想要实现MVCC,需要通过回表读聚集索引来实现。


结论2,辅助索引中不存储DB_TRX_ID,需要依托聚集索引实现MVCC


3. 问题3:为什么查找数据时,一定要读取叶子节点,只读非叶子节点不行吗

在辅助索引的根节点这个页面中(pageno=4),我们注意到它记录的最小记录(min_rec)对应的是(c1=NULL, id=9)这条记录。

在它指向的叶子节点页面中(pageno=18)也确认了这个情况。

现在把id=9的记录删掉,看看辅助索引数据页会发生什么变化。

[root@yejr.run]> delete from t_sk where id = 9 and c1 is null;
Query OK, 1 row affected (0.01 sec)



先检查第4号数据页。

[root@yejr.run]# innodb_space -s ibdata1 -T test/t_sk -p 4 page-dump

...
records:
{:format=>:compact,
:offset=>126,
:header=>
{:next=>428,
:type=>:node_pointer,
:heap_number=>2,
:n_owned=>0,
:min_rec=>true,
:deleted=>false,
:nulls=>["c1"],
:lengths=>{},
:externs=>[],
:length=>6},
:next=>428,
:type=>:secondary,
:key=>[{:name=>"c1", :type=>"INT UNSIGNED", :value=>:NULL}],
:row=>[{:name=>"id", :type=>"INT UNSIGNED", :value=>9}],
:sys=>[],
:child_page_number=>18,
:length=>8}
...



看到第四号数据页中,最小记录还是 id=9,没有更新。

再查看第18号数据页。

[root@yejr.run]# innodb_space -s ibdata1 -T test/t_sk -p 18 page-dump
...
records:
{:format=>:compact,
:offset=>136,
:header=>
{:next=>146,
:type=>:conventional,
:heap_number=>3,
:n_owned=>0,
:min_rec=>false,
:deleted=>false,
:nulls=>["c1"],
:lengths=>{},
:externs=>[],
:length=>6},
:next=>146,
:type=>:secondary,
:key=>[{:name=>"c1", :type=>"INT UNSIGNED", :value=>:NULL}],
:row=>[{:name=>"id", :type=>"INT UNSIGNED", :value=>30}],
:sys=>[],
:length=>4}
...

在这个数据页(叶子节点)中,最小记录已经被更新成 id=30 这条数据了。

可见,索引树中的非叶子节点数据不是实时更新的,只有叶子节点的数据才是最准确的。

结论3,在索引树中查找数据时,最终一定是要读取叶子节点才行


4. 问题4:索引列允许为NULL,会额外存储更多字节吗

之前流传有一种说法,不允许设置列值允许NULL,是因为会额外多存储一个字节,事实是这样吗?

我们先把c1列改成NOT NULL DEFAULT 0,当然了,改之前要先把所有NULL值更新成0。

[root@yejr.run]> update t_sk set c1=0 where c1 is null;
[root@yejr.run]> alter table t_sk modify c1 int unsigned not null default 0;



在修改之前,每条索引记录长度都是10字节,更新之后却变成了13个字节。

直接对比索引页中的数据,发现不同之处

#允许为NULL,且默认值为NULL时
{:format=>:compact,
:offset=>136,
:header=>
{:next=>146,
:type=>:conventional,
:heap_number=>3,
:n_owned=>0,
:min_rec=>false,
:deleted=>false,
:nulls=>["c1"],
:lengths=>{},
:externs=>[],
:length=>6},
:next=>146,
:type=>:secondary,
:key=>[{:name=>"c1", :type=>"INT UNSIGNED", :value=>:NULL}],
:row=>[{:name=>"id", :type=>"INT UNSIGNED", :value=>48}],
:sys=>[],
:length=>4}


#不允许为NULL,默认值为0时
{:format=>:compact,
:offset=>138,
:header=>
{:next=>151,
:type=>:conventional,
:heap_number=>3,
:n_owned=>0,
:min_rec=>false,
:deleted=>false,
:nulls=>[],
:lengths=>{},
:externs=>[],
:length=>5},
:next=>151,
:type=>:secondary,
:key=>[{:name=>"c1", :type=>"INT UNSIGNED", :value=>0}],
:row=>[{:name=>"id", :type=>"INT UNSIGNED", :value=>48}],
:sys=>[],
:length=>8}

可以看到,原先允许为NULL时,record header需要多一个字节(共6字节),但实际物理存储中无需存储NULL值。

而当设置为NOT NULL DEFAULT 0时,record header只需要5字节,但实际物理存储却多了4字节,总共多了3字节,所以索引记录以前是10字节,更新后变成了13字节,实际上代价反倒变大了。

列值允许为NULL更多的是计算代价变大了,以及索引对索引效率的影响,反倒可以说是节省了物理存储开销。

结论4,定义列值允许为NULL并不会增加物理存储代价,但对索引效率的影响要另外考虑

最后,本文使用的MySQL版本Percona-Server-5.7.22,下载源码后自编译的。

Server version:        5.7.22-22-log Source distribution



5. 几点总结

最后针对InnoDB辅助索引,总结几条建议吧。

a) 索引列最好不要设置允许NULL。

b) 如果是非索引列,设置允许为NULL基本上无所谓。

c) 辅助索引需要依托聚集索引实现MVCC。

d) 叶子节点总是存储最新数据,而非叶子节点则不一定。

e) 尽可能不SELECT *,尽量利用覆盖索引完成查询,能不回表就不回表。

6. 延伸阅读


Enjoy MySQL :)


全文完。

            </div>
相关文章
|
存储 关系型数据库 MySQL
【MYSQL】金额(金钱)相关的数据存储类型
int 对于游戏币等代币,一般存储为int类型是可行的。 问题在于越界,int类型长度为11位。 在存储人民币相关的金额的时候,则只能存储到9长度的人民币,也就是说,最大只能存储999999999,不到10亿的数值,如果业务增长很快的话,就会给自己留下隐患。
5210 0
|
搜索推荐 数据挖掘 UED
中小企业CRM解决方案排名:性价比之选
中小企业在选择CRM系统时面临的主要痛点包括预算有限、需求多样、IT资源匮乏等。因此,他们需要寻找高性价比、功能全面、操作简便且具备灵活性和可扩展性的解决方案。本文推荐了纷享销客、Zoho CRM、Apptivo和简道云CRM等几款适合中小企业的CRM系统,这些系统不仅能满足企业的多样化需求,还能助力企业高效管理客户关系,提升销售业绩。
|
JavaScript 安全
SharePoint Online 部署SPFx Web部件
【8月更文挑战第10天】在SharePoint Online中部署SPFx Web部件需先安装Node.js及Yeoman等工具,通过Yo生成器创建项目。开发Web部件后,使用`gulp`命令构建、打包并生成.sppkg文件。接着,在SharePoint管理中心的应用程序目录上传并部署该解决方案包至目标网站。最后,通过编辑页面插入Web部件进行测试,确保遵循最佳实践并维护更新。
228 1
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的电影院订票选座系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的电影院订票选座系统的详细设计和实现(源码+lw+部署文档+讲解等)
235 0
|
Linux
Linux中/etc/hosts文件总是被自动修改
关闭NetworkManager服务即可。 临时关闭: service  NetworkManager stop 永久关闭: chkconfig NetworkManager off 在centos6.x系列Linux版本修改完/etc/hosts之后重启被修改,是由于NetworkManager服务,关闭后再修改hosts文件,重启就不会变回去了。
4377 0
|
NoSQL Shell Android开发
GDB在线调试Android Framework Native C/C++代码
一、准备工作 1、下载并编译Android系统源码 这里比较灵活,可以下载公司内部机型的代码,也可以下载原生AOSP的代码 环境配置参考 https://source.
4356 0
|
运维 自然语言处理
【大模型】LLM 如何处理域外或无意义的提示?
【5月更文挑战第5天】【大模型】LLM 如何处理域外或无意义的提示?
|
存储 Java 编译器
Java语言之float、double内存存储方式
Java语言之float、double内存存储方式
877 0
|
传感器
西门子 PCS 7 工程师站及 PDM 如何安装?
本篇我们来介绍一下西门子 PCS 7 工程师站及 PDM 如何安装。我们先来看一张图,下图显示了西门子PCS7系统中各类PC站的系统结构。在安装过程中,应该根据每个PC站的不同功能定义来选择正确的安装选项。
西门子 PCS 7 工程师站及 PDM 如何安装?
|
JSON 缓存 前端开发
🎉🎉 开源啦!一款基于Vue3 + Vite + TS的简历制作神器~~
目前市面上有不少在线制作简历的网站,不得不说,有些做得很好,提供的简历模板非常的漂亮!但是,相信有很多小伙伴不会去使用它们,毕竟贫穷会限制我们! 当然,有些小伙伴可能会去下载各种各样的简历模板,比如一些word格式的模板,但是这些模板还是存在一个问题,就是样式太难调了,扩展性不高。 因为,我作为众多小伙伴中的一员,就想充分发挥自己程序员的能力,于是便有了这款免费的开源简历制作神器!
467 0
🎉🎉 开源啦!一款基于Vue3 + Vite + TS的简历制作神器~~