1. 基本概念

索引(index):是一种数据结构,通过记录搜索码和维护一个指向表中数据的指针或引用,使得查询操作可以跳过全表扫描,直接定位到目标数据,用于快速查找数据库表中的特定记录

类型顺序索引(Orderd)散列索引(Hash)
操作按照搜索码的值进行排序按照搜索码的散列函数值将数据分布到多个桶中
适用ORDERD BYBETWEEN=IN
优势适合范围查询,时间复杂度高适合精准查询,时间复杂度低
劣势插入和删除操作的成本高破坏了顺序信息

2. 顺序索引

2.1 聚集和辅助

类型聚集索引(Clustered )辅助索引(Secondary)
定义数据顺序与索引顺序一致数据存储顺序与索引顺序无关
特性一个表只能有一个聚集索引一个表可以有多个辅助索引
适用范围查询多条件查询

聚集索引

辅助索引

2.2 稠密和稀疏

类型稠密索引(dense)稀疏索引(sparse)
定义每条数据都有索引只有部分数据有索引
特性辅助索引是稠密的稀疏索引是聚集的
适用等值查询范围查询

2.3 多级索引

多级索引:将索引结构分为多个层级,每一层索引都是对下一层数据的索引

2.4 桶索引

用于处理非唯一搜索码,索引包含指向桶的指针,每个桶包含指向记录的指针

3. B+树索引

3.1 树结构

  • 平衡性:所有叶子节点位于同一层
  • 有序性:所有叶子节点按顺序从左到右连接,形成一个有序链表
  • 内部节点/索引节点:存储指向索引的指针,用于引导搜索过程
  • 叶子节点/数据节点:存储指向数据的指针
  • 阶:节点最多可以拥有的孩子个数

3.2 节点结构

若阶为n,则有:

  • 非根非叶节点至少有n/21\lceil n/2 \rceil - 1个关键字
  • 叶节点至少有(n1)/2\lceil (n-1)/2 \rceil个关键字
  • 每个节点的指针数量总是比关键字数量多1
  • 每个节点的关键字数量最多有n-1个
  • 每个节点的指针数量最多有n个

叶子节点:代表着稠密索引

  • 指针pip_i指向具有关键字kik_i的一条文件记录
  • 最后一个指针pnp_n指向下一个叶子节点

内部节点:代表着多级稀疏索引

  • 指针p1p_1指向搜索码值小于k1k_1的子树
  • 指针pnp_n指向搜索码值小于km1k_{m-1}的子树
  • 指针pip_i指向ki1k_{i-1} \leq 搜索码值<ki< k_i的子树

3.3 查找操作

假设每个节点的搜索码列表用key表示,指针列表用point数组表示,搜索码是value

  1. 从根节点开始node = root
  2. 在当前节点中找到满足 value <= node.key[i] 的最小 i
    1. 如果 i 不存在,则 node = node.point[-1]
    2. 如果 value = node.key[i],则 node = node.point[i+1]
    3. 如果 value < node.key[i],则 node = node.point[i]
  3. 重复第2步直到叶子结点,找到满足 key[i] = value的 i,返回 node.point[i]

实际上,B+树也可以在所有叶子节点组成的链表上遍历搜索,一种是随机查找,一种是顺序查找,前者适合单值查询,后者适合范围查询

3.4 插入操作

  1. 寻找插入位置:根据关键字的顺序,从根节点出发,递归地查找合适的叶子节点,在该节点中插入新关键字
  2. 叶子节点插入:如果目标叶子节点此时关键字个数小于nn,则结束,否则进入第3步
  3. 叶子节点分裂:将这个叶子节点分裂成左和右两个叶子节点
    1. 左叶子节点包含前n/2\lfloor n/2 \rfloor个关键字,右叶子节点包含剩下的关键字
    2. 将第n/2+1\lfloor n/2 \rfloor + 1个关键字插入到父节点中,其中该关键字的左边指针指向左叶子结点,右边指针指向右叶子节点
    3. 若当前父节点的关键字的个数小于n,则结束,否则进入第4步
  4. 内部节点分裂:将这个内部节点分裂成左和右两个内部节点
    1. 左内部节点包含前n/2\lfloor n/2 \rfloor个关键字,右内部节点包含剩下的关键字
    2. 将第n/2+1\lfloor n/2 \rfloor + 1个关键字插入到父节点中,其中该关键字的左边指针指向左叶子结点,右边指针指向右叶子节点
    3. 递归执行上述过程直到结束或者父节点是根节点,进入第5步
  5. 创建新根节点:将原根节点的第n/2+1\lfloor n/2 \rfloor + 1个关键字提升到新根节点,令新根节点的左指针指向分裂后的左子节点,右指针指向分裂后的右子节点(树的高度+1)

3.5 删除操作

  1. 寻找目标关键字位置:从根节点出发,根据关键字的顺序递归查找目标关键字所在的叶子节点,如果关键字不存在,删除操作结束,否则进入第2步
  2. 删除关键字:在目标叶子节点中直接删除该关键字,同时如果该关键字是内部节点的分隔关键字,需要修改分隔关键字为更大的关键字,如果删除后关键字数量大于等于(n1)/2\lceil (n-1)/2 \rceil,则删除操作结束,否则进入第3步
  3. 借关键字:选择左兄弟或右兄弟中关键字数量大于n/21\lceil n/2 \rceil - 1的节点,如果不存在这样的兄弟节点则进入第4步
    1. 如果是左兄弟节点:借最大关键字,更换父节点中对应关键字为左兄弟节点的次大关键字
    2. 如果是右兄弟节点:借最小关键字,更换父节点中对应关键字为右兄弟节点的次小关键字
  4. 合并节点
    1. 如果有左兄弟节点则合并左兄弟节点,否则合并右兄弟节点
    2. 如果是叶子结点合并,删除父节点中的对应关键字
    3. 如果是内部节点合并,将父节点中分隔关键字下移到合并节点中
    4. 递归处理父节点,直到满足关键字要求或父节点是根节点,进入第5步
  5. 根节点调整:直接删除空的根节点即可(树的高度-1)

推荐一个可视化B+树的网址:

4. Mysql使用索引

4.1 命令

创建索引

1
create index 索引名 on 表(属性);

删除索引

1
drop index 索引名;

4.2 存储引擎

类型InnoDBMyISAMMEMORY
索引类型聚集索引,索引存储数据辅助索引,索引存储指向数据的地址散列索引,数据存储在内存中
索引结构B+树索引B+树索引散列索引
特性支持事务和外键约束适用于以读为主的场景支持极高的查询性能,但不适合范围查询

4.3 默认索引

主键索引:添加primary key约束,数据库会自动创建主键索引,是聚集索引

唯一索引:添加unique约束,数据库会自动创唯一索引,是辅助索引