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>
相关文章
|
存储 SQL 关系型数据库
InnoDB索引允许NULL对性能有影响吗(1)
InnoDB索引允许NULL对性能有影响吗
101 0
|
存储 SQL 关系型数据库
InnoDB索引允许NULL对性能有影响吗(2)
InnoDB索引允许NULL对性能有影响吗
|
存储 关系型数据库 MySQL
InnoDB索引允许NULL对性能有影响吗(3)
InnoDB索引允许NULL对性能有影响吗
|
6天前
|
Kubernetes 安全 Devops
【云效流水线 Flow 测评】驾驭云海:五大场景下的云效Flow实战部署评测
云效是一款企业级持续集成和持续交付工具,提供免费、高可用的服务,集成阿里云多种服务,支持蓝绿、分批、金丝雀等发布策略。其亮点包括快速定位问题、节省维护成本、丰富的企业级特性及与团队协作的契合。基础版和高级版分别针对小型企业和大规模团队,提供不同功能和服务。此外,云效对比Jenkins在集成阿里云服务和易用性上有优势。通过实战演示了云效在ECS和K8s上的快速部署流程,以及代码质量检测和AI智能排查功能,展示了其在DevOps流程中的高效和便捷,适合不同规模的企业使用。本文撰写用时5小时,请各位看官帮忙多多支持,如有建议也请一并给出,您的建议能帮助我下一篇更加出色。
121139 10
|
11天前
|
机器学习/深度学习 数据采集 人工智能
人类生产力的解放?揭晓从大模型到AIGC的新魔法
本文从介绍大模型的概念延伸到大模型的革命意义。作者讲述了通过大模型的加持,让AIGC有了更多的可能性。
126715 5
|
10天前
|
存储 Prometheus 并行计算
10倍性能提升-SLS Prometheus 时序存储技术演进
本文将介绍近期SLS Prometheus存储引擎的技术更新,在兼容 PromQL 的基础上实现 10 倍以上的性能提升。同时技术升级带来的成本红利也将回馈给使用SLS 时序引擎的上万内外部客户。
89159 4
|
11天前
|
人工智能 弹性计算 算法
一文解读:阿里云AI基础设施的演进与挑战
对于如何更好地释放云上性能助力AIGC应用创新?“阿里云弹性计算为云上客户提供了ECS GPU DeepGPU增强工具包,帮助用户在云上高效地构建AI训练和AI推理基础设施,从而提高算力利用效率。”李鹏介绍到。目前,阿里云ECS DeepGPU已经帮助众多客户实现性能的大幅提升。其中,LLM微调训练场景下性能最高可提升80%,Stable Difussion推理场景下性能最高可提升60%。
|
12天前
|
机器人 Linux API
基于Ollama+AnythingLLM轻松打造本地大模型知识库
Ollama是开源工具,简化了在本地运行大型语言模型(ile优化模型运行,支持GPU使用和热加载。它轻量、易用,可在Mac和Linux上通过Docker快速部署。AnythingLLM是Mintplex Labs的文档聊天机器人,支持多用户、多种文档格式,提供对话和查询模式,内置向量数据库,可高效管理大模型和文档。它也是开源的,能与Ollama结合使用,提供安全、低成本的LLM体验。这两款工具旨在促进本地高效利用和管理LLMs。
139635 27
|
13天前
|
消息中间件 安全 API
Apache RocketMQ ACL 2.0 全新升级
RocketMQ ACL 2.0 不管是在模型设计、可扩展性方面,还是安全性和性能方面都进行了全新的升级。旨在能够为用户提供精细化的访问控制,同时,简化权限的配置流程。欢迎大家尝试体验新版本,并应用在生产环境中。
103856 2
|
13天前
|
Kubernetes Cloud Native 容灾
OpenKruise v1.6 版本解读:增强多域管理能力
OpenKruise 在 2024.3 发布了最新的 v1.6 版本(ChangeLog),本文对新版本的核心特性做整体介绍。
93374 3