2024/4/19 MySQL索引结构

本文详细介绍了MySQL中的B+树索引类型、InnoDB引擎的数据结构,讨论了为何选择B+树,以及聚类索引和非聚类索引的区别。此外,还探讨了插入操作对B+树的影响和如何计算大数据量下B+树的高度。

MySQL有哪些索引类型?

MySQL支持B+树索引、哈希索引、全文索引三种索引类型。
我比较常用的是B+树索引,因为它是InnoDB引擎默认使用的索引类型,支持排序、分组、范围查询、模糊查询等功能。

InnoDB引擎的所以数据结构是什么?

InnoDB存储引擎支持两种索引数据结构,B+树索引和FULLTEXT索引。

MySQL为什么使用B+树?

  • B+树是多叉树,平衡二叉树、红黑树是二叉树,在同等数据量下,平衡二叉树、红黑树高度更高,磁盘IO次数更多,性能更差,而且它们会频繁执行再平衡过程,来保证树形结构平衡。
  • 跳表和B+树相比,跳表在极端情况下会退化为链表,平衡性差,而数据库查询需要一个可预期的查询时间,并且跳表需要更多内存。
  • B树和B+树相比,B树的数据存储在全部节点中,对查询范围不友好。非叶子结点存储了数据,导致内存中难以放下全部非叶子结点。如果内存放不下非叶子节点,那么就意味着查询非叶子结点的时候都需要磁盘IO。
  • B+树与哈希表相比。哈希表索引不支持范围查询和排序操作,不支持联合索引最左匹配原则,如果重复键值比较多,还容易造成哈希碰撞导致效率进一步降低。

聚类索引和非聚类索引有什么区别?

聚类索引和非聚类索引最主要的区别是B+树叶子结点存放的内容不同。
存放的内容不同:

  • 聚簇索引的B+树叶子结点存放的是主键值+完整的记录
  • 非聚类索引的B+树叶子结点存放的是索引值+主键值

如果查询语句的查询条件用了二级索引,但是查询的数据不是主键值,也不是二级索引值,这时在二级索引找到主键后,就需要回表才能查到数据,需要扫描两次B+树。如果查询的数据是主键值时,因为只在二级索引就能查询到,这时就会用到覆盖索引,不需要回表,只需要扫描一次B+树。

insert 操作对 B+ 树结构的改变是怎么样的?

B+ 树的数据都是有序的,所以

  • 如果我们使用主键是顺序递增,那么每次插入的新数据就会顺序插入到叶子结点最右边的节点里,如果该页面满了,就会自动开辟一个新页面,将数据插入到新页面。因此每次插入一条新纪录,都是追加操作,不需要重新移动数据,因此这种插入数据的方法效率非常高。
  • 如果我们使用主键不是顺序递增,由于每次插入主键的索引值都是随机的,因此每次插入新的数据时,就可能会插入到现有数据页中间的某个位置,这时候为了保证B+树的有序性,要移动其他数据来满足新数据的插入。如果该页面满了,就发生页分裂,这时候要从一个页面复制数据到另一个页面,目的时保证后一个数据页中的所有行主键值比前一个数据页中主键值大,也分裂可能会造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率。

所以,在设计主键的时候,最好采用自增的方式,或者顺序递增主键值。

假如一张表有两千万的数据,B+树的高度是多少?怎么算的?

假设
非叶子节点内指向其他页的数量为 x
叶子节点内能容纳的数据行数为 y
B+ 树的层数为 z
表总数会等于 x 的 z-1 次方与 y 的乘积

具体要看数据库表的字段多不多,以及字段类型,假设一行记录是1KB大小,那么2000万的数据表,B+树大概是三层高度
MySQL数据页的大小是16KB,去掉一些头信息,大概有15KB是可以存储数据。
在索引页中主要记录的是主键与页号,假设是主键id类型是bigint,那就是8字节,页号固定为4字节,那么索引页中一条数据也就是12byte,那么一个索引页可以存储 15 * 1024 / 12 ≈ 1280 个页号
叶子节点中存放的是真正的行数据,这个影响的因素就会多很多,比如字段的类型,字段的数量。每行数据占用空间越大,页中所放的行数量就会越少假设一条行数据1KB来算,那么一页就能存下15条
根据公式 Total = x(z-1) * y,已知 x = 1280, y = 15, 假设 B+ 树是三层,那就是z = 3, Total = (1280 ^2) * 15 = 24576000 (约 2.45kw)

<think>首先,用户的问题是关于Elasticsearch的索引库和索引结构。我需要根据系统级指令来构建回答。关键系统级指令: -所有行内数学表达式必须使用$...$格式。但在这个上下文中,可能没有数学表达式,所以我可以忽略。-独立公式必须使用$$...$$格式并单独成段。同样,可能不适用。 -LaTeX语法正确:确保任何公式都正确。-使用中文回答:整个回答必须用中文。-生成相关问题:在回答结束时,添加相关问题。-回答中引用的段落末尾自然地添加引用标识:例如[^1]。-回答结构清晰,帮助用户逐步解决问题。 -保证回答真实可靠:基于提供的引用内容。 提供的引用内容: -[^1]:定义了Elasticsearch中的Schema(模式)主要是Mapping,它定义了索引中文档字段的结构、数据类型、存储和索引方式。Mapping就是Schema。 -[^2]:比较了Elasticsearch与MySQL的术语:索引类似表,文档类似行,字段类似列,Mapping类似Schema。 -[^3]:描述了mapping属性,包括type、index、analyzer、properties等。 -[^4]:类似[^3],列出了字段数据类型。 用户的问题:"我想了解Elasticsearch是否有索引库以及其索引结构是什么"基于引用:- Elasticsearch确实有索引库(Index),类似于数据库中的表。 -索引结构主要由Mapping定义,包括字段的类型、是否索引等属性。 回答结构:1.**确认索引库的存在**:解释Elasticsearch中的索引是什么。2.**解释索引结构**:详细描述Mapping及其属性。 3. **逐步解决问题**:从基本概念到细节。 4. **添加引用标识**:在相关句子末尾添加[^1],[^2]等。 5. **生成相关问题**:在结束部分添加相关问题。相关问题生成: -基于主题,生成3-4个相关问题,如:1.如何创建Elasticsearch索引库?2.Mapping属性的具体应用有哪些?3. Elasticsearch索引的性能优化方法?4.如何查询索引库中的文档?确保回答真实可靠:使用提供的引用内容,不要添加外部知识。最终回答大纲: -开头:直接回答用户问题。 -主体:-解释索引库:类似于数据库的表。-描述索引结构:Mapping定义字段。-列出常见Mapping属性。 -结尾:相关问题。</think>### Elasticsearch 索引库及其索引结构 在 Elasticsearch 中,确实存在索引库(Index),它是文档(Document)的集合,类似于传统数据库中的表(Table)。索引库是 Elasticsearch 的核心组件,用于存储、检索和管理数据。索引结构主要由 Mapping(映射)定义,它类似于数据库的 Schema(模式),决定了文档字段的结构、数据类型、存储和索引方式[^1][^2]。下面我将逐步解释索引库的概念和索引结构,确保回答基于可靠引用。 #### 1. **索引库的概念** - **索引库是什么?** 索引库是 Elasticsearch 中存储文档的逻辑容器。每个索引库对应一个或多个分片(Shards),用于分布式存储数据。例如,创建一个名为 "products" 的索引库,可以存储商品信息文档[^2]。 - 与传统数据库类比: - Elasticsearch 索引库 ≈ MySQL 的表(Table) - 文档(Document) ≈ 表中的行(Row) - 字段(Field) ≈ 表中的列(Column) - Mapping(映射) ≈ Schema(表结构)[^2] 这确保了数据的组织性和查询效率。 - **索引库的作用** 索引库支持高效的数据操作,包括: - 存储文档(如 JSON 格式的数据)。 - 支持全文搜索、聚合分析等。 - 通过分布式架构实现高可用和扩展性[^1][^3]。 #### 2. **索引结构:Mapping(映射)** 索引结构的核心是 Mapping,它定义了索引库中文档的约束规则。Mapping 指定了每个字段的数据类型、索引行为、分词方式等属性,确保数据的一致性和查询性能[^1][^3]。以下是 Mapping 的主要属性: - **字段数据类型(type)** Mapping 定义了字段的类型,常见类型包括: - 字符串:`text`(可分词的文本,适用于全文搜索)、`keyword`(精确值,适用于过滤或聚合,如品牌或国家)[^3][^4]。 - 数值:`long`、`integer`、`short`、`byte`、`double`、`float`(用于数值计算)。 - 布尔:`boolean`(true/false)。 - 日期:`date`(存储时间戳)。 - 对象:`object`(嵌套 JSON 结构)。 例如,一个商品索引库的 Mapping 可能包含 `name`(text 类型)、`price`(float 类型)等字段[^3][^4]。 - **索引行为(index)** 该属性控制字段是否被索引(默认为 `true`)。如果设置为 `false`,字段不会被搜索或聚合,但可存储原始数据(适用于不需要查询的字段)[^3]。 - **分词器(analyzer)** 对于 `text` 类型字段,指定分词器(如标准分词器或自定义分词器),影响文本如何被分词和搜索。例如,使用 `ik_smart` 分词器处理中文文本[^3]。 - **子字段(properties)** 用于定义嵌套字段或复杂对象。例如,一个 `address` 字段可能包含子字段 `city`(keyword 类型)和 `street`(text 类型)[^3]。 - **其他属性** 包括 `format`(日期格式)、`ignore_above`(忽略超长 keyword 字段)等,用于优化存储和查询[^1][^3]。 **示例 Mapping 结构**(以 JSON 格式表示): ```json { "mappings": { "properties": { "name": { "type": "text", "analyzer": "ik_max_word" }, // 可分词的文本字段 "brand": { "type": "keyword" }, // 精确值字段 "price": { "type": "float" }, // 数值字段 "created_at": { "type": "date", "format": "yyyy-MM-dd" } // 日期字段 } } } ``` 此 Mapping 确保 "name" 字段支持全文搜索,"brand" 字段用于精确匹配[^3][^4]。 #### 3. **索引库的创建与管理** - 创建索引库时,通常通过 REST API 定义 Mapping。例如: ```bash PUT /products { "mappings": { "properties": { "name": { "type": "text" }, "category": { "type": "keyword" } } } } ``` 这创建了一个名为 "products" 的索引库,并指定了字段结构[^2][^3]。 - 索引库支持动态 Mapping(Elasticsearch 自动推断字段类型)或静态 Mapping(用户显式定义),后者更可靠以避免数据不一致[^1]。 总之,Elasticsearch 的索引库是数据存储的基础单元,索引结构由 Mapping 严格定义,确保字段类型、索引行为等约束,从而优化搜索和分析性能[^1][^2][^3][^4]。如果您有具体场景(如电商搜索),我可以进一步解释如何设计索引
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值