为什么数据库索引数据结构使用B+树,而不使用xxx?

简介: 为什么数据库索引数据结构使用B+树,而不使用xxx?

这个问题其实还是很有趣的,我在上一篇文章中,写了:

1、为什么数据库索引不能用二叉排序树;

2、为什么数据库索引不能用红黑树;

本篇文章增加了:

1、为什么不能使用哈希表;

2、为什么不能使用B-树;

3、为什么能使用B+树。

一、为什么数据库的索引不能用二叉搜索树?

根据上面的演示,看着二叉搜索树也是可以的呀,也挺快嘛。

但是为什么用在数据库底层不合适呢?这也是面试时常问的。

我们可以演示一下:

https://www.cs.usfca.edu/~galles/visualization/BST.html

我们假设我们给Col1加上索引,那么依次对二叉搜索树插入:1、2、3、4、5、6、7;

可以看到退化成了一个链表的形式。

当我们查询7的话,时间复杂度就变成了单链表一样了。

从大到小也是:

总结如下:

  • 如果数据库底层使用二叉搜索树的话,遇到数据为极端的情况下会退化成单链表,所以不太合适;

可以想象一下,如果我们给自增的一列使用二叉搜索树的索引数据结构的话,是不是就很倒霉了。这就是极端的情况,都在一边。

二、为什么红黑树不适合数据库索引?

红黑树又叫:二叉平衡树

红黑树作为Java开发人员应该很耳熟吧,JDK8中的HashMap中的底层数据结构就用到了红黑树。

这么牛逼的JDK中都用到了红黑树,为什么数据库中的索引数据结构不太适合呢?

还是上面那个假设,假设我们给Col1加上红黑树的索引。

过程如下动态演示:

如果我们执行:

select * from table1 where Col1 = 7;

动态演示如下:

可以看到,我们一共查询了4次就查到了。与没加这个索引之前还是有比较大的效果的,至少没有全部扫描。

总结:

通过观察可以看到,每次插入几乎都会去调整这颗二叉树,保持高度是平衡的。

如果数据量非常大的话,也是非常耗时的,所以红黑树也是不太合适。

三、为什么不能使用Hash数据结构作为索引的数据结构呢?

当你点进这篇文章的时候,肯定对于Hash表是熟悉的了。

Hash表的话,简单点说有这么几个特点:

  • 1、数据插入的位置由哈希值决定,顺序无序的;
  • 2、插入很快;
  • 3、查找也很快;

我们拿一组数据来插入哈希表试试:

100、13、101、14、103、109

我们使用https://www.cs.usfca.edu/~galles/visualization/ClosedHash.html来动态模拟Hash表;

为了表现出来Hash表为什么不适用与数据库,我们顺序插入准备好的数据:

动态演示如下:

结果如下:

1、

我们在数据库中经常使用sql来查询一个范围的数据例如:

select * from t where id < 15;

我们知道哈希表是无序的,所以就凭借这一点,就比较困难。

心里应该也有数了,哈希表是肯定不可以的。

2、

从插入数据的动态演示中可以看到,100和13的哈希值都是13。

那么就会向后移动(这也是哈希表解决冲突的一种方式)。

例如:我们先插入100,然后插入13;

我们想查找13的话,就会比较慢了。

两个数可能体现不出来,1万个?10万个?100万个数呢?可想而知,就相当于进行了全表扫描。

所以,哈希表总体来说,不合适。

四、为什么不能使用B-树

B-Tree就是B树,不叫B减树。

我们继续来模拟:

https://www.cs.usfca.edu/~galles/visualization/BTree.html

插入1-10,10个数后:

B树确实解决了我们上面所说的哈希表的查找范围的问题。

我们执行下列sql:

select * from t where id > 5;

(1)首先查找到5

查找路径为:4–>6–>5;

(2)然后返回上一层查找到6

(3)然后查找到6

(4)…

可以看到会有一个回旋的过程,随着数据量的增长,回旋的过程也就越多,那么所浪费的时间也就越多。

五、为什么能使用B+树

我们使用这个来模拟:

https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html

构造一个1-10的数的B+树;

先来介绍以下这颗树:

一共分为两部分,叶子节点和非叶子节点。

  • 叶子节点是由链表实现的,凡是插入的数据,全都链接在一起。
  • 非叶子节点只存key;
  • 叶子节点即存key又存value;

key:0-10这个数字;

value:0-10的数字的地址。

解决了B树中回旋查找的问题。查找效率也整体提高了。

例如:

select * from t where id > 5;

看下图:

可以看到,先查找非叶子节点5、然后7、然后6,最终查找到叶子节点5。

查找到之后,就可以顺序取出了,就不必继续回去上一层了。

目录
相关文章
|
1月前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因?
B+树优化了数据存储和查询效率,数据仅存于叶子节点,便于区间查询和遍历,磁盘读写成本低,查询效率稳定,特别适合数据库索引及范围查询。
39 6
|
2月前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因
B+树相较于B树,在数据存储、磁盘读写、查询效率及范围查询方面更具优势。数据仅存于叶子节点,便于高效遍历和区间查询;内部节点不含数据,提高缓存命中率;查询路径固定,效率稳定;特别适合数据库索引使用。
33 1
|
2月前
|
数据库 索引
数据库索引
数据库索引 1、索引:建立在表一列或多列的辅助对象,目的是加快访问表的数据。 2、索引的优点: (1)、创建唯一性索引,可以确保数据的唯一性; (2)、大大加快数据检索速度; (3)、加速表与表之间的连接; (4)、在查询过程中,使用优化隐藏器,提高系统性能。 3、索引的缺点: (1)、创建和维护索引需要耗费时间,随数据量增加而增加; (2)、索引占用物理空间; (3)、对表的数据进行增删改时,索引需要动态维护,降低了数据的维护速度。
40 2
|
2月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
363 1
|
2月前
|
存储 关系型数据库 数据库
Postgres数据库BRIN索引介绍
BRIN索引是PostgreSQL提供的一种高效、轻量级的索引类型,特别适用于大规模、顺序数据的范围查询。通过存储数据块的摘要信息,BRIN索引在降低存储和维护成本的同时,提供了良好的查询性能。然而,其适用场景有限,不适合随机数据分布或频繁更新的场景。在选择索引类型时,需根据数据特性和查询需求进行权衡。希望本文对你理解和使用PostgreSQL的BRIN索引有所帮助。
64 0
|
2月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
143 0
|
14天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
39 3
|
14天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
42 3
|
14天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
56 2
|
27天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
185 15