mysql的B+树索引

这篇文章是自己学习mysql随手写的杂记,编辑混乱且不够严谨,请勿参考,谢谢!

以mysql中的innodb引擎为例,索引是个什么东西?为什么说索引即数据?一个2层B+树索引最多可以存多少条数据?聚簇索引,二级索引,联合索引?

在单个页中进行记录查找分为:

  • 定位记录所在的槽
  • 遍历槽比对记录

真实的场景中,表中的数据会分布在很多的页中。记录的查找也在这些页中进行,如果我们不进行任何查找优化,最简单粗暴的办法就是遍历这些所有页中,显然效率低下。可以参考一个页中进行记录查找的思路,mysql规定:

  • 一个页中的记录主键值大于上一个页中的主键值,如果一个页中的空间不够新记录存储,则会产生一个新页用以存储新记录,新页也符合此规则,这就是"页分裂"

于是,把每个页中的页号、最小记录的主键值提取出来放在目录项页中,目录项页中的数据存储主键+页号。这些记录的记录类型值为1,表明是目录项记录,且页中最小记录的min_rec_mask为1,表示是B+树非叶子节点最小记录。这些页中的数据其实就是索引。mysql自动会为表创建聚簇索引,其特点如下:

主键有序性

  • 页之间按记录主键大小从小到大形成双链表。
  • 页中记录按主键从小到大形成单链表。
  • 目录项同一层中,按照主键从小到大形成双链表。

聚簇索引的叶子节点存储的是完整的用户记录,其非叶子节点(内节点)存储的是目录项记录,忘记说明一点:一个页会对应一个目录项(主键值+页号)。每个页或目录项页都是一个节点。

如果目录项页太多则继续向上抽象出新的页以存储这些存储目录项页的信息。在记录查找时,则是:

  • 定位记录所在的页(记录多时会先定位目录项页)。
  • 再在页中定位记录。

B+树页有一个根节点,这个根节点的页号是自B+树产生时就固定不变的,其存储在某个地方,当需要查找数据时则会找到这个根节点页号,后续再进行查找。

到这里说的都是聚簇索引,目录项页存储的数据是主键+页号。那么对于一个非主键列的精确查找,如col=zhangsan。

col为普通的列,并非主键列,则目录项中存储的数据为col+主键+页号,此为二级索引。咦?为什么多一个主键值?原因是如果列值一样的,这个时候就需要按主键大小要做区分了,不然innodb无法区分哪个在前,哪个在后。在查找用户的记录时,根据列值在列对应B+树索引中只能找到目标记录的主键,这个时候还要去聚簇索引中的叶子节点取出具体的用户记录,这种查找记录的形式为回表。

通常情况下,一颗B+树不会超过4层。我们看看一棵2层的B+树可以存储多少条记录:

假设一个页中可以存储1000条数据,一个目录项页可以存储1000条目录项记录,则总的记录条数为:1000x1000=1000000,一百万的数据量,三层就上亿了,能够存储的数据量非常之大。

联合索引是把多个列联合起来做成索引,如col1,col2,则是先按col1排序,如果col1相同则按col2排序,一个联合索引就是一棵B+树,不同于对这些列建立的索引。

完。

<think>嗯,用户想比较MySQL中B+索引和哈希索引的优缺点及适用场景。首先,我需要回忆一下这两种索引的基本结构和工作原理。B+索引是一种多路平衡查找,而哈希索引则是基于哈希表实现的。两者的结构差异会导致不同的查询性能表现。 根据引用[3],B+索引适合范围查询和排序,而哈希索引在等值查询上更快。那用户可能需要知道什么情况下选择哪种索引更好。比如,如果应用中有很多范围查询,B+更合适;如果是精确查找,哈希可能更高效。 接下来,要考虑它们的存储结构。引用[4]提到B+的内部节点只存索引,不存数据,这样减少存储空间。而哈希索引可能需要处理哈希冲突,这会影响性能。这点需要详细说明。 性能对比方面,B+的查询时间复杂度是O(log n),哈希则是平均O(1),但最坏情况可能退化为O(n)。但实际中哈希冲突管理好的话,还是高效的。不过B+在范围查询时效率更高,这也是为什么MySQL默认使用B+的原因之一。 使用场景的话,用户可能需要知道何时选择哈希索引。比如内存表或者需要快速查找键值的场景。而B+适用于需要排序、分组或者范围查找的情况,比如订单时间范围查询。 另外,需要提到哈希索引不支持部分索引和覆盖索引,而B+支持,这点在优化查询时很重要。例如,如果查询只需要索引列,B+可以直接返回数据,而哈希需要回表。 还要注意MySQL的存储引擎支持情况,比如InnoDB的自适应哈希索引功能,用户可能不知道这个特性,可以解释一下。 最后,总结两者的优缺点,给出实际应用中的建议,帮助用户根据具体需求选择合适的索引类型。同时,确保回答结构清晰,分点明确,让用户容易理解。</think>### MySQL B+索引与哈希索引对比分析 #### 一、核心区别 1. **数据结构** - **B+索引**:多路平衡搜索,数据存储在叶子节点,形成有序链表[^4] 例如:$$ \text{非叶节点}(K_1,K_2,...,K_n) \rightarrow \text{叶节点}(D_1,D_2,...,D_n) $$ - **哈希索引**:基于哈希表实现,通过哈希函数将键值映射到桶位置 2. **查询模式** - B+支持$范围查询$(如`BETWEEN`、`>`、`<`)和排序操作 - 哈希索引仅支持$等值查询$(`=`、`IN()`),无法处理范围查询[^3] #### 二、性能对比 | 维度 | B+索引 | 哈希索引 | |------------|--------------------------|-------------------------| | 查询时间复杂度 | $O(\log N)$ | 平均$O(1)$,最差$O(N)$ | | 范围查询效率 | 高(顺序访问叶子节点)[^4] | 不支持 | | 排序性能 | 天然有序 | 需要额外排序步骤 | | 索引维护成本 | 插入/删除需要平衡 | 哈希冲突需处理链式结构 | #### 三、存储特性 1. **B+优势** - 支持$覆盖索引$(索引包含查询字段) - 内部节点不存储数据,节省空间[^4] 例如:$$ \text{存储效率}=1-\frac{\text{数据节点数}}{\text{总节点数}} $$ - 支持多列联合索引的最左前缀匹配 2. **哈希局限** - 无法使用索引完成排序 - 不支持部分索引(如`LIKE 'prefix%'`) - 哈希冲突会降低性能 #### 四、典型应用场景 1. **优先选择B+** - 订单系统的日期范围查询 ```sql SELECT * FROM orders WHERE order_date BETWEEN '2023-01-01' AND '2023-06-30' ``` - 需要`ORDER BY`的报表查询 - 联合索引查询(如`(last_name, first_name)`) 2. **适合哈希索引** - 内存表(MEMORY引擎)的高速等值查询 ```sql SELECT session_data FROM user_sessions WHERE session_id = 'a1b2c3' ``` - 数据仓库的精确匹配ETL过程 - InnoDB自适应哈希索引(自动缓存热点数据)[^1] #### 五、选择建议 1. **OLTP系统**:90%以上使用B+索引 2. **OLAP系统**:在明确只有点查询时考虑哈希索引 3. **混合负载**:使用InnoDB自适应哈希索引,自动平衡两者优势
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值