文章插图
哈喽 , 大家好 , 我是了不起 。面试的时候 , 面试官总喜欢问一些关于MySQL索引的问题 , 但是如果单纯的记忆 , 还是有难度的;今天了不起把MySQL索引的知识点进行汇总 , 方便大家快速记忆MySQL索引的相关知识点 。赶快收藏此文章吧!
索引结构:B+树
索引其实是一种数据结构MySQL中的B+Tree
注意B+树是MySQL , 索引默认的结构;一张表至少有一个索引(主键索引) , 是可以有多个索引的
- 非叶子节点也叫内部节点 , 只存储 健值(主键的值) + 指针(存储子节点的地址信息)
非主键索引:非主键列的值 + 指向下一个节点的指针(存储子节点的地址信息)
- 所有的数据都存在叶子节点中;
- 同时叶子节点上还存有一个指向相邻叶子节点的指针
- 如果是聚簇索引(主键索引) , 叶子节点存储的是实际数据
- 【MySQL索引,快速记忆法】如果是非聚簇索引 , 则保存的是聚簇索引的索引key , 也就是主键索引的值;查询非聚簇索引会有一个回表操作
- B+Tree的每个叶子节点增加了一个指向相邻叶子节点的指针 , 它的最后一个数据会指向下一个叶子节点的第一个数据 , 形成了一个有序链表的结构 。
- B+ 树的磁盘读写代价更低 B+ 树的数据都集中在叶子节点 , 分支节点 只负责指针(索引);B 树的分支节点既有指针也有数据。这将导致B+ 树的层高会小于B 树的层高 , 也就是说B+ 树平均的Io次数会小于B 树 。
- B+ 树的查询效率更加稳定 B+ 树的数据都存放在叶子节点 , 故任何关键字的查找必须走一条从根节点到叶子节点的路径 。所有关键字的查询路径相同 , 每个数据查询效率相当 。
- B+树更便于遍历 由于B+树的数据都存储在叶子结点中 , 分支结点均为索引 , 遍历只需要扫描一遍叶子节点即可;B树因为其分支结点同样存储着数据 , 要找到具体的数据 , 需要进行一次中序遍历按序来搜索 。
- B+树更擅长范围查询 B+树叶子节点存放数据 , 数据是按顺序放置的双向链表 。B树范围查询只能中序遍历 。
- B+ 树占用内存空间小 B+ 树索引节点没有数据 , 比较小 。在内存有限的情况下 , 相比于B树索引可以加载更多B+ 树索引 。
- InnoDB支持事务 , MyISAM不支持
- InnoDB支持外键 , 而MyISAM不支持
- InnoDB是聚集索引 , 数据和索引存到同一个文件里;MyISAM是非聚集索引 , 数据和索引不在同一个文件里;都是使用B+Tree作为索引结构
- InnoDB不保存表的具体行数 , 执行select count(*) from table时需要全表扫描 。而MyISAM用一个变量保存了整个表的行数 , 执行上述语句时只需要读出该变量即可 , 速度很快(注意不能加有任何WHERE条件)
因为InnoDB的事务特性 , 在同一时刻表中的行数对于不同的事务而言是不一样的 , 因此count统计会计算对于当前事务而言可以统计到的行数 , 而不是将总行数储存起来方便快速查询 。InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引 。如果二级索引不存在 , InnoDB还会尝试去遍历其他聚簇索引 。
如果索引并没有完全处于InnoDB维护的缓冲区(Buffer Pool)中 , count操作会比较费时 。可以建立一个记录总行数的表并让你的程序在INSERT/DELETE时更新对应的数据 。和上面提到的问题一样 , 如果此时存在多个事务的话这种方案也不太好用 。如果得到大致的行数值已经足够满足需求可以尝试SHOW TABLE STATUS
推荐阅读
- 带你读 MySQL 源码:Where 条件怎么过滤记录?
- 如何快速减掉小肚腩,5个消除内脏脂肪的秘诀,从168到122
- 有MySQL了,为什么还硬要搭个MongoDB集群?
- go语言中经常犯的错误
- MySQL Router高可用搭建,你学会了吗?
- 微软CEO:AI快速发展并不可怕
- 抖音小店评分怎么快速提高?
- Apache Iceberg 中引入索引提升查询性能
- 在 Meta 构建和部署 MySQL Raft
- 干香菇如何快速泡好