百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

索引实现靠的是树,你知道么?(索引实现原理,数据结构)

toyiye 2024-08-19 22:35 11 浏览 0 评论

之前朋友在面试的时候被问到了许多关于索引的问题,而索引这个词一直也是我们在开发中最最最常见的,也是很多在进行代码优化的时候会去做的一件事情,所以今天我们来说说面试中关于索引的那点事。

索引

什么是索引?

索引其实是数据库的一种术语,在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的特定信息。

但是面试的时候一般不会问你索引是什么?而是喜欢去问,为什么要去使用索引,它的底层是怎么实现的?那数据库又应该怎么去优化呢?下面我们就从这三个方面去解释一下这些面试中的要点信息。

索引底层实现

索引的实现通常使用B树及其变种B+树。

B-Tree 是最常用的用于索引的数据结构。因为它们是时间复杂度低, 查找、删除、插入操作都可以可以在对数时间内完成。另外一个重要原因存储在B-Tree中的数据是有序的。

哈希表是另外一种你可能看到用作索引的数据结构-这些索引通常被称为哈希索引。使用哈希索引的原因是,在寻找值时哈希表效率极高。所以,如果使用哈希索引,对于比较字符串是否相等的查询能够极快的检索出的值。

我们以MySQL数据库的索引为例子。

既然说到了索引的实现是通过B树和变种B+树,那我们来说说这个B树和B+树。

B树

我们看个图。图中所示,B树事实上是一种平衡的多叉查找树,也就是说最多可以开m个叉(m>=2),我们称之为m阶b树,我给大家多画一点内容,这也是我专门看视频的时候记录下的一些自己的心得。

图中其实画的是比较简单的,但是如果说我们画一个三阶的,这个时候就可以是这样子的

这就是说最多能开三个叉,但是里面有可能有两个叉的,以最多的叉来算。

m阶B树满足以下条件

  • 每个节点至多可以拥有m棵子树。
  • 根节点,只有至少有2个节点(要么极端情况,就是一棵树就一个根节点,单细胞生物,即是根,也是叶,也是树)。
  • 非根非叶的节点至少有的Ceil(m/2)个子树(Ceil表示向上取整,图中3阶B树,每个节点至少有2个子树,也就是至少有2个叉)。
  • 非叶节点中的信息包括[n,A0,K1,A1,K2,A2,…,Kn,An],,其中n表示该节点中保存的关键字个数,K为关键字且Ki<Ki+1,A为指向子树根节点的指针。
  • 从根到叶子的每一条路径都有相同的长度,也就是说,叶子节在相同的层,并且这些节点不带信息,实际上这些节点就表示找不到指定的值,也就是指向这些节点的指针为空。

B树的查询过程和二叉排序树比较类似,从根节点依次比较每个结点,因为每个节点中的关键字和左右子树都是有序的,所以只要比较节点中的关键字,或者沿着指针就能很快地找到指定的关键字,如果查找失败,则会返回叶子节点,即空指针。

B树搜索的简单伪算法如下:

BTree_Search(node, key) {
    if(node == null) return null;
    foreach(node.key)
    {
        if(node.key[i] == key) return node.data[i];
            if(node.key[i] > key) return BTree_Search(point[i]->node);
    }
    return BTree_Search(point[i+1]->node);
}

data = BTree_Search(root, my_key);

对于每个结点,主要包含一个关键字数组Key[],一个指针数组(指向儿子)Son[]。在B-Tree内,查找的流程是:使用顺序查找(数组长度较短时)或折半查找方法查找Key[]数组,若找到关键字K,则返回该结点的地址及K在Key[]中的位置;否则,可确定K在某个Key[i]和Key[i+1]之间,则从Son[i]所指的子结点继续查找,直到在某结点中查找成功;或直至找到叶结点且叶结点中的查找仍不成功时,查找过程失败。

关于B-Tree有一系列有趣的性质,例如一个度为d的B-Tree,设其索引N个key,则其树高h的上限为logd((N+1)/2)logd((N+1)/2),检索一个key,其查找节点个数的渐进复杂度为O(logdN)O(logdN)。从这点可以看出,B-Tree是一个非常有效率的索引数据结构。

B+树

B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用B+Tree实现其索引结构。

B+ 树是一种树数据结构,是一个n叉树,每个节点通常有多个孩子,一颗B+树包含根节点、内部节点和叶子节点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点。

B+ 树通常用于数据库和操作系统的文件系统中。

NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系统都在使用B+树作为元数据索引。

B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。

B+ 树元素自底向上插入。

看节点之间有重复元素,而且在叶子节点上还用指针连接在了一起,而这些就是B+树的几个特点

  1. 每个父节点的元素都出现在了子节点中,分别是子节点最大或者最小的元素。
  2. 在上面的这一棵树中,根节点元素8是子节点258的最大的元素,根元素15也是。这时候要注意了,根节点最大的元素等同于整个B+树的最大的元素,以后无论是怎么插入或者是删除,始终都要保持最大的元素在根节点中。
  3. 叶子节点,因为父节点的元素都出现在了子节点当中,因此所有的叶子节点包含了全量的元素信息。

那么既然B+树是B树的的一种变形树,那么差异点在哪呢?

B+树与B树差异

有k个子节点的节点必然有k个元素

非叶子节点仅具有索引作用,跟记录有关的信息均存放在叶子节点中

树的所有叶子节点构成一个有序链表,可以按照元素排序的次序遍历全部记录

B树和B+树的区别在于,B+树的非叶子节点只包含导航信息,不包含实际的值,所有的叶子节点和相连的节点使用链表相连,便于区间查找和遍历。

B+树的优点

由于B+树在内部节点上不包含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子节点上关联的数据也具有更好的缓存命中率。

B+树的叶子节点都是相连的,因此只要遍历叶子节点就可以实现整颗树的遍历。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历,相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。

B+树的缺点

但是B树也有优点,其优点在于,由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速。

因为B+树比B树的读写代价更低,所以B+树比B树更适合操作系统的文件索引和数据库索引。

那么既然基层实现我们理解完了,是不是该说一下这个数据库索引分类了呢?

数据库索引分类

根据数据库的功能,可以在数据库设计器中创建四种索引:普通索引、唯一索引、主键索引和聚集索引。

普通索引

最基本的索引类型,没有唯一性之类的限制。普通索引可以通过以下几种方式创建:创建索引,例如 CREATE INDEX <索引的名字> ON tablename (列的列表);

修改表,例如 ` ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表)` ;

创建表的时候指定索引,例如 CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) ) ;

唯一索引

唯一索引是不允许其中任何两行具有相同索引值的索引。

当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在 employee 表中职员的姓 (lname) 上创建了唯一索引,则任何两个员工都不能同姓。

对某个列建立UNIQUE索引后,插入新记录时,数据库管理系统会自动检查新纪录在该列上是否取了重复值,在CREATE TABLE 命令中的UNIQE约束将隐式创建UNIQUE索引。 创建唯一索引的几种方式:

创建索引,例如 CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表) ;

修改表,例如 ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表) ;

创建表的时候指定索引,例如 ` CREATE TABLE tablename ( […], UNIQUE [索引的名字] (列的列表) ) ` ;

主键索引

简称为主索引,数据库表中一列或列组合(字段)的值唯一标识表中的每一行。该列称为表的主键。在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。提示尽管唯一索引有助于定位信息,但为获得最佳性能结果,建议改用主键索引。

聚集索引

也称为聚簇索引,在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引, 即如果存在聚集索引,就不能再指定CLUSTERED 关键字。

索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。聚集索引更适用于对很少对基表进行增删改操作的情况。

如果在表中创建了主键约束,SQL Server将自动为其产生唯一性约束。在创建主键约束时,指定了CLUSTERED关键字或干脆没有制定该关键字,SQL Sever将会自动为表生成唯一聚集索引。

而如果是面试过程中很多就会问你是索引的分类和怎么使用的,最后我们再来说怎么操作索引。

操作索引

创建索引

SQL3没有提供建立索引的方法。但是,从事DBMS开发、销售的公司都提供他们具有这种功能的SQL工具。因为这些工具不是标准化的,它们相互不同。SQL语言使用CREATE INDEX 语句建立索引,其一般格式是:



CREATE [UNIQUE] [CLUSTERED| NONCLUSTERED] INDEX <索引名> ON <表名>(<列名>[ASC|DESC] [, <列名>[ASC|DESC]...])

说明:与表一样,索引也需要有唯一的名字,且基于一个表来建立,可以根据表中的一列或者多列,当列的顺序都是升序默认可不必标出,当属性列有按照降序排列的,所有属性的升序降序都不要标明。

– UNIQUE——建立唯一索引。

– CLUSTERED——建立聚集索引。

– NONCLUSTERED——建立非聚集索引。

– ASC——索引升序排序。

– DESC——索引降序排序。

修改索引 对于已经建立的索引,如果需要对其重新命名,可以使用ALTER INDEX 语句。其一般格式为

ALTER INDEX <旧引索名字> RENAME TO<新引索名>

删除索引

当某个时期基本表中数据更新频繁或者某个索引不再需要时,需要删除部分索引。SQL语言使用DROP INDEX 语句删除索引,其一般格式是:

DROP INDEX<索引名>

删除索引时,DBMS不仅在物理删除相关的索引数据,也会从数据字典删除有关该索引的描述。

关于索引你会了吗?

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码