数据库-索引及其数据结构

本文介绍了MySQL索引的本质,是帮助高效获取数据的排好序的数据结构。详细阐述了B-Tree和B+Tree的特点及差异,还分析了MyISAM和InnoDB的索引实现方式,重点探讨了InnoDB索引性能,如使用磁盘I/O次数评价优劣,利用预读和局部性原理优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.索引的本质

索引是帮助MySQL高效获取数据的排好序的数据结构。

索引存储在文件里(硬盘里)
索引结构

  • 二叉树(红黑树)
  • HASH
  • BTREE
    在这里插入图片描述
    磁盘存取原理
  • 寻道时间(速度慢,费时)
  • 旋转时间(速度较快)
    一次I/O
    在这里插入图片描述

2.B-Tree

  • 度(Degree)–节点的数据存储个数
  • 叶节点具有相同的深度
  • 叶节点的指针为空
  • 节点中的数据key从左到右递增排序
B-树是一种多路搜索树(并不一定是二叉的)

1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树(或B-树、B_树)。
一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。

它或者是空树,或者是满足下列性质的树:

  1. 根结点至少有两个子女;
  2. 每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;
  3. 除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ;
  4. 所有的叶子结点都位于同一层。
特点:

是一种多路搜索树(并不是二叉的):

  1. 定义任意非叶子结点最多只有M个儿子;且M>2;
  2. 根结点的儿子数为[2, M];
  3. 除根结点以外的非叶子结点的儿子数为[M/2, M];
  4. 每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
  5. 非叶子结点的关键字个数=指向儿子的指针个数-1;
  6. 非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
  7. 非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的
    子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;
  8. 所有叶子结点位于同一层;
    如:(M=3)
    在这里插入图片描述

3.B+Tree(B-Tree变种)

  • 非叶节点不存储data,只存储key,可以增大度
  • 叶子节点不存储指针
  • 叶子节点多了横向指针顺序访问指针,可范围查找,提高区间访问的性能

B+树是应文件系统所需而出的一种B-树的变型树。

一棵m阶的B+树和m阶的B-树的差异在于:
  1. 有n棵子树的结点中含有n个关键字,每个关键字不保存数据,只用来索引,所有数据都保存在叶子节点。

  2. 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

  3. 所有的非终端结点可以看成是索引部分,结点中仅含其子树(根结点)中的最大(或最小)关键字。
    通常在B+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。

B+树是B-树的变体,也是一种多路搜索树:
  1. 其定义基本与B-树同,除了:
  2. 非叶子结点的子树指针与关键字个数相同;
  3. 非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树
    (B-树是开区间);
  4. 为所有叶子结点增加一个链指针;
  5. 所有关键字都在叶子结点出现;
B+的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树可以在非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;
B+的特性:
  1. 所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好
    是有序的;
  2. 不可能在非叶子结点命中;
  3. 非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储
    (关键字)数据的数据层;
  4. 更适合文件索引系统;
    在这里插入图片描述

4.MyISAM索引实现(非聚集)

  • 索引文件和数据文件时分离的(.frm结构文件和.MYD数据文件和.MYI索引文件)
    主键索引与非主键索引无区别:
    在这里插入图片描述

5.InnoDB索引实现(聚集)

  • 数据文件本身就是B+Tree组织的一个索引结构文件(.frm结构文件和.idb数据和索引文件)
  • 聚集索引-叶节点包含了完整的数据记录
  • 为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?
    数据文件本身就是B+Tree组织的一个索引结构文件,主键索引就是聚集索引,不建默认自动建索引。用字符串不如整型比较快,字符串需要先转成ASCII,整型省空间,int占32位。不可用UUID,因为UUID不一定自增,可能造成B+Tree分裂。
  • 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)

主键索引与非主键索引有区别:
聚集索引通常就是主键索引
-
辅助索引就是非聚集索引,只包含索引列和一个用于查找对应行记录的『书签』
在这里插入图片描述
B+Tree节点中关键字冗余问题?

为什么mysql页文件默认16K?

6.InnoDB索引性能分析

  • 一般使用磁盘I/O次数评价索引结构的优劣。
  • 预读:磁盘一般会顺序向后读取一定长度的数据(页的整数倍)放入内存。
  • 局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。
  • B+Tree节点的大小设为等于一个页,每次新建节点直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,就实现了一个节点的载入只需一次I/O.
  • 一般操作系统的最小存储单元为页,1页大小为4K。
  • 查看MySQL文件页大小(16K):SHOW GLOBAL STATUS like ‘Innodb_page_size’
    在这里插入图片描述
<think>我们正在讨论图数据库索引数据结构。图数据库与传统关系型数据库不同,其数据模型基于图结构(节点、边、属性),因此索引结构也需要适应这种模型。图数据库常用的索引数据结构包括: 1. **哈希索引**:用于快速查找节点或边的属性值。 2. **B+树索引**:用于范围查询和排序,尤其在属性索引中常见。 3. **LSM树(Log-Structured Merge-Tree)**:用于写密集型场景,很多图数据库底层使用NoSQL存储(如RocksDB),而RocksDB使用LSM树。 4. **位图索引**:适用于低基数属性(例如性别、状态等)的快速多条件查询。 5. **全文索引**:如Lucene倒排索引,用于文本搜索。 6. **图结构特有的索引**:如邻接索引(Adjacency Index)和反向邻接索引(Reverse Adjacency Index)用于快速遍历图。 具体到图数据库- **Neo4j**:使用Lucene进行全文索引,对于属性索引,Neo4j 3.x之前使用手动创建的索引(底层是Lucene),而Neo4j 4.x引入了新的索引结构(如范围索引、文本索引等)。对于图遍历,Neo4j使用节点和关系的存储文件,并通过指针连接(类似于邻接列表),因此不需要额外的索引来遍历关系,因为关系直接存储在节点上(每个节点维护指向其关系的指针链表)。 - **JanusGraph**(基于TinkerPop):底层存储可以使用多种后端(如Cassandra、HBase、BerkeleyDB等)。对于属性索引,它使用Elasticsearch、Solr或Lucene。图遍历的索引则依赖于底层的存储,例如在Cassandra上使用全局索引(如Elasticsearch)来加速查询。 - **Dgraph**:使用BadgerDB(键值存储,使用LSM树)作为底层存储,并且使用一种称为“谓词索引”的结构(每个谓词(边)都有一个索引,默认为哈希索引,也可以配置为倒排索引、全文索引等)。此外,Dgraph还使用Roaring位图进行快速集合操作。 因此,图数据库索引数据结构是多样化的,通常结合多种索引技术来满足不同的查询需求。下面我们详细说明几种常见的索引数据结构及其在图数据库中的应用: 1. **B+树索引**: - 用于范围查询和精确匹配,例如查询年龄在20到30岁之间的所有节点。 - 在图数据库中,B+树常用于属性索引。例如,Neo4j可以创建基于B+树的索引(实际上Neo4j的索引在底层使用Lucene,但Lucene内部也使用了类似B+树的结构)。 2. **哈希索引**: - 提供O(1)时间复杂度的点查询,适用于等值查询。 -数据库中的节点ID或边ID的快速查找常使用哈希索引。例如,Dgraph中默认的谓词索引就是哈希索引。 3. **LSM树**: - 用于写优化,将随机写转换为顺序写,提高写入性能。 - 很多图数据库的底层存储使用LSM树,例如JanusGraph使用Cassandra(LSM树)作为存储后端,Dgraph使用BadgerDB(基于LSM树)。 4. **位图索引**: - 适用于低基数属性的快速组合查询(AND/OR)。 -数据库中,当属性只有少数几个可能值时(如用户类型:普通用户、VIP用户),位图索引可以高效地组合多个条件。 5. **全文索引(倒排索引)**: - 用于文本搜索,例如在节点的属性中搜索关键字。 - Neo4j和JanusGraph都支持使用Lucene或Elasticsearch提供全文索引功能。 6. **图特有索引**: - **邻接索引**:每个节点存储其出边(或入边)的列表,这样在遍历图时可以直接获取邻居。这种结构在Neo4j中通过“关系链”实现(每个节点有一个指向第一个关系的指针,每个关系有指向下一个关系的指针,形成链表)。 - **反向邻接索引**:为了加速反向遍历(如查找指向某个节点的边),有些图数据库会额外存储反向边(如Dgraph中每个谓词都有正向和反向索引)。 此外,一些图数据库还使用**自适应基数树(ART)**作为索引结构,如Hyper数据库(虽然Hyper不是图数据库,但ART树也被一些图数据库采用)。ART树是一种高效的内存索引结构,适合作为内存数据库索引。例如,Memgraph(另一个图数据库)就使用了ART树作为其内存索引。 总结:图数据库索引数据结构不是单一的,而是根据不同的查询需求(点查询、范围查询、全文搜索、图遍历等)使用多种数据结构。同时,图数据库还会针对图结构设计专门的索引(如邻接索引)来加速图遍历操作。 下面我们通过一个示例(Neo4j)来说明索引的使用: ```cypher // 创建索引 CREATE INDEX ON :Person(name); // 查询时会使用索引 MATCH (p:Person) WHERE p.name = 'Alice' RETURN p; ``` 在Neo4j中,创建索引后,底层会使用Lucene索引(基于倒排索引和B+树混合)来加速查询。 参考文献: [^1] 提到了InnoDB使用B+树作为索引结构,图数据库在属性索引上也可能使用B+树。 [^2] 提到聚簇索引索引和数据保存在一起,而图数据库通常没有聚簇索引的概念(因为图结构不同于表),但有些图数据库会将节点和关系存储在连续区域(类似聚簇)来加速遍历。 [^3] 提供了创建索引的指导原则,这些原则同样适用于图数据库(例如在经常搜索的属性上创建索引)。 [^4] 提到了ART树,这是一种高效的内存索引结构,可能被图数据库(如Memgraph)采用。 因此,图数据库索引数据结构的选择取决于具体的使用场景和数据库的实现。 相关问题: 1. 图数据库中如何加速深度遍历(如2度以上关系查询)? 2. 图数据库索引和关系型数据库索引有何异同? 3. 图数据库如何实现全文索引? 4. 图数据库中的索引更新是立即生效的吗? 5. 图数据库索引对写入性能的影响如何?</think>### 图数据库索引数据结构解析 图数据库索引设计与传统关系型数据库有显著差异,其核心目标是高效处理**图结构数据**(节点、边、属性)。以下是主流图数据库使用的索引数据结构及其原理: --- ### 一、核心索引类型 #### 1. **属性索引(Property Indexes)** - **数据结构**: - **B+树**:用于范围查询和排序(如查询年龄>30的用户)[^2][^3] - **LSM树(Log-Structured Merge-Tree)**:优化写入性能(如JanusGraph使用) - **哈希索引**:支持精确匹配查询(如`WHERE name="Alice"`) - **应用场景**: 快速查找具有特定属性值的节点/边(如标签、权重等)。 #### 2. **图结构索引(Graph Structure Indexes)** - **邻接索引(Adjacency Lists)** - 每个节点存储其**出边/入边列表** - 数据结构- **压缩位图(Roaring Bitmaps)**:高效存储边ID(如Dgraph) - **跳表(Skip Lists)**:支持快速边遍历(如Neo4j的底层存储) - **应用场景**: 加速邻居节点查询(如“查找用户A的所有好友”)。 #### 3. **全文索引(Full-Text Indexes)** - **数据结构**: - **倒排索引(Inverted Index)**:将属性值映射到节点ID(如Neo4j集成Lucene) - **应用场景**: 文本模糊搜索(如描述中包含“图数据库”的节点)。 #### 4. **空间索引(Spatial Indexes)** - **数据结构**: - **R树/R\*树**:高效处理多维空间数据(如地理位置) - **应用场景**: 地理围栏查询(如“查找5公里内的餐厅”)。 --- ### 二、创新数据结构 #### 1. **自适应基数树(ART - Adaptive Radix Tree)** - **原理**: 动态调整节点键切片长度,平衡存储与查询效率[^4] - **优势**: - 内存占用比B+树低8倍 - 支持前缀搜索(如查找以“user_”开头的ID) - **应用**: Memgraph(内存图数据库)的核心索引结构。 #### 2. **图感知索引(Graph-Aware Indexes)** - **子图索引(Subgraph Indexing)**: 预计算频繁查询的子图模式(如“公司-员工-部门”三角关系) - **路径索引(Path Indexes)**: 存储常见路径的压缩表示(如社交网络的“二度人脉”) --- ### 三、典型图数据库实现对比 | 数据库 | 索引数据结构 | 特点 | |-----------|----------------------------------|----------------------------------------------------------------------| | **Neo4j** | B+树(属性)、跳表(邻接关系) | 属性索引与图结构分离,支持Lucene全文索引[^1] | | **Dgraph**| Roaring位图(边)、ART树(属性) | 基于BadgerDB(LSM树),位图加速多边遍历 | | **JanusGraph**| 弹性搜索(全文)、B+树 | 依赖后端存储(Cassandra/HBase),支持混合索引 | --- ### 四、设计选择的关键因素 1. **查询模式**: - 点查询 → 哈希/ART树 - 范围查询 → B+树 - 图遍历 → 邻接索引 2. **存储介质**: - 内存数据库(如Memgraph)优先ART树 - 磁盘数据库(如Neo4j)多用B+树 3. **一致性要求**: - 强一致性场景需牺牲写入性能(如B+树) - 最终一致性场景可用LSM树 > **核心原则**:图数据库索引需同时优化 **属性过滤** 和 **图拓扑遍历** 效率[^3]。 --- ### 相关问题 1. 图数据库中如何处理超大规模边的索引? 2. ART树相比B+树在图场景下的性能优势如何量化? 3. 图遍历索引如何避免深度查询的性能瓶颈? 4. 分布式图数据库的全局索引如何实现? 5. 图数据库索引更新如何保证ACID特性? [^1]: InnoDB的数据文件本身就是按B+树组织的索引结构文件 [^2]: 聚簇索引索引和数据保存在同一个B+树中,访问更快 [^3]: 索引应创建在经常搜索、排序、范围查询或连接的列上 [^4]: ART树通过自适应键切片长度优化存储和查询效率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值