在这道题的评论中,有个人回复此题的意义,说 “像是 mysql 的 B+树 的数据结构,这个 next 就是为了范围搜索的时候,不用再次遍历整个树,而是从begin 位置找 next 节点一直找到不满足条件的节点即可。需要强调的一点是,mysql 的 B+ 树只在叶子节点上建立 next 指针,非叶子节点不会有 next 指针。”
而且,之前的面试时,面试官曾经问我索引的作用,特此来复习一下。
1. 索引
索引是对数据库表中 一列或多列的值 进行排序 的一种结构。其一个主要目的是 加快对表中数据的查找或者排序。
例如:
select * from table1 where id=10000
1)如果没有索引,必须遍历整个表,直到 id=10000 这一行被找到;
2)在 ID 这列上建立索引后,即可在索引中查找,由于索引是经过某种算法优化过的,因此查找的次数要少很多。
所以,索引是用来快速定位的。
根据数据库的功能,可在数据库设计器中创建三种索引:
1)唯一索引
2)主键索引
数据库表中经常有一列或多列组合,其值来唯一标识表中的每一行。该列成为表的主键。为表定义主键,则将自动创建主键索引。主键索引是唯一索引的特定类型。
3)聚集索引
定义:表中 行的物理顺序 与 列值(一般是主键的那一列)的逻辑(索引)顺序 相同。一个表中只能有一个聚集索引。
如下图中,id为主键,根据主键建立了聚集索引(即主键索引其实就是聚集索引)。
所以,“ 行的物理顺序 与 列值(一般是主键的那一列)的逻辑(索引)顺序 相同 ”,如果我们查询 id 比较靠后的数据,那么这行数据的地址在磁盘中的物理地址也会比较靠后。由于物理排列方式 与 聚集索引 的顺序相同,所以也就只能建立一个聚集索引了。
A clustered index is a special type of index that reorders the way which records in the table are physically stored.
聚集索引相当于数据在数据库中一行行记录的编号,来描述这一行行数据的物理存储顺序。
3.1)默认聚集索引(Default Clustered Indexes)
3.2)自定义聚集索引(Custom Clustered Indexes)
4)非聚集索引
现在该作者建立的非聚集索引是 Name
聚集索引 和 非聚集索引 的应用场景
- 索引的数量
很明显,如果需要在数据库上创建多个索引,使用非聚集索引。因为表中只能有一个聚集索引。 - SELECT 操作
如果你想要在"name"列上创建索引,而且你只想要 SELECT 出 name,非聚集索引会很快。
但是,如果你想要 使用 name 来 SELECT 出其它列的值,如age、gender,非聚集索引会慢,因为它会先在索引中搜索 name,接着在相应的表记录中去搜索 age 和 gender。
使用聚集索引,由于所有记录都已经排序,如果数据是从具有聚集索引的列以外的列中选择的,那么SELECT操作将会更快。
下面这段英文语法不错:
3. INSERT/UPDATE操作
使用非聚集索引的话,INSERT 和 UPDATE 操作更快,因为在执行 INSERT 或者 UPDATE 操作时,不需要对实际记录进行排序。
4. 硬盘空间
由于非聚集索引与原始表存储在不同位置,因此非聚集索引会消耗额外的磁盘空间。磁盘空间不足的话,使用聚集索引。
5. 最终结论
根据经验,每个表应该至少有一个聚集索引,最好是用于SELECTING records的列并且包含唯一值的列。主键列是聚集索引的理想候选项。
2. B+树
2.1 外存储器:计算机的辅助存储器,包括硬盘、软盘、光盘等。将数据存储到磁盘中,每次查找某个元素的时候都要去磁盘中查找,然后再写入内存中,容量大,但是查询效率低。
2.2 内存储器:指计算机的主存储器和位于CPU与主存储器之间的高速缓冲存储器cache。将数据放在内存中,查询快,但是内存容量小。
2.3 存储最小单元:计算机在存储数据时,有最小存储单元。计算机磁盘存储数据的最小存储单元是扇区(通常情况下,每个扇区的大小是512字节,一个字节为8bit);文件系统的最小存储单元是块(Block),一个块的大小是4KB,1KB=1024字节,所以一个块相当于8个扇区;InnoDB存储引擎的最小存储单元是页,一个页的大小是16K,相当于32个扇区。
数据表中的数据都是存储在页中的,假设一行数据的大小是1K,那么一个页可以存放16行这样的数据。
索引一般以文件形式存储在磁盘上,所以索引检索需要磁盘I/O操作,磁盘I/O操作存在机械运动耗费,因此磁盘I/O的时间消耗是巨大的。
页,是计算机管理存储器的逻辑块,操作系统将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页的大小通常为4K)。主存和磁盘以页为单位交换数据。 当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。所以,IO一次就是读取一页的大小。
2.4 平衡二叉树:又被称为AVL树,它的性质为它是一棵空树或者它的左右两个子树的高度差的绝对值不超过1。这里的平衡二叉树一般是基于二叉查找树,要将此二叉查找树调整为平衡二叉树,用来缩短一个二叉查找树的查找时间。
2.5 B树:B树和平衡二叉树的不同之一:1)B树属于多叉树,又叫做平衡多路查找树(查找路径不只有两个)。数据库索引技术里大量使用B树和 B+树的数据结构。如下图所示,字母按照26个英文字母的大小排序(C>B>A)。B树和平衡二叉树的不同之二:2)每个节点包含的关键字增多了。
2.6 B+树:B+树相对于B树来说,1)所有关键词存储在叶子节点,非叶子节点不存储真正的data;2)为所有的叶子节点增加了一个链指针。因为内部节点并不存储data,所以一般B+树的叶子节点和内节点的大小不同,而B树的每个节点的大小一般是相同的,为一页。
以查询节点key为50的data:
从根节点索引到叶子节点,时间复杂度固定为O(log n)。
B+树叶节点两两相连可增加区间访问性。
2.7 空间局部性原理:如果一个存储器的某个位置被访问,那么它附近的位置也会被访问。
若我们访问节点 key 为50,则key为 55/60/62的节点将来也很可能被访问,可以提前将这些数据读入内存,减少了磁盘IO的次数。
磁盘分block,一次磁盘IO会读取若干个block,具体是和操作系统有关的。由于磁盘 IO 数据大小是固定的,在一次IO中,单个元素越小,数据量就越大。所以说B+树的单次磁盘IO的信息量大于B-树。B+树在一次IO里面,能读出的索引值更多,从而减少查询时候需要的IO次数。
索引本身也很大,不可能全部存储在内存中,所以,索引往往以索引文件的形式存储在磁盘上。 索引的查找过程要产生磁盘IO消耗。
参考:
数据库索引
还不知道B+树 ?看完,别再问我什么是B+树 了
你能说出SQL聚集索引和非聚集索引的区别吗?
When to Use Clustered or Non-Clustered Indexes in SQL Server
什么是B+树
B+树和B树的区别