最是人间留不住,朱颜辞镜花辞树.
目录
一.为什么需要索引
1.什么是索引 2.索引的创建原则
二.理解索引
1. MySQL与磁盘交互基本单位
2.索引的结构
a.关于hash索引,B树索引,B+树索引的特点
B树 B+树 HASH
b.为什么使用InnoDB 存储引擎选择使用 B+Tree 索引结构?
3.聚簇索引和非聚簇索引
辅助(普通)索引
三.MySQL索引的操作
一.为什么需要索引
1.什么是索引
索引:提高数据库的性能,索引是物美价廉的东西了。不用加内存,不用改程序,不用调sql,只要执行 正确的 create index ,查询速度就可能提高成百上千倍。但是天下没有免费的午餐,查询速度的提高 是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的IO。所以它的价值,在于提高一个 海量数据的检索速度。
2.索引的创建原则
- 比较频繁作为查询条件的字段应该创建索引
- 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
- 更新非常频繁的字段不适合作创建索引
- 不会出现在where子句中的字段不该创建索引
二.理解索引
1. MySQL与磁盘交互基本单位
MySQL 作为一款应用软件,可以想象成一种特殊的文件系统。它有着更高的IO场景,所以,为了提高 基本的IO效率, MySQL 进行IO的基本单位是 16KB (后面统一使用 InnoDB 存储引擎讲解) 也就是说,磁盘这个硬件设备的基本单位是 512 字节,而 MySQL InnoDB引擎 使用 16KB 进行IO交互。 即, MySQL 和磁盘进行数据交互的基本单位是 16KB(以InnoDB存储引擎为例) 。这个基本数据单元,在 MySQL 这里叫做page(注 意和系统的page区分)
建立共识
- MySQL中的数据文件,是以page为单位保存在磁盘当中的。
- MySQL的CURD操作,都需要通过计算,找到对应的插入位置,或者找到对应要修改或者查询的数据。
- 而只要涉及计算,就需要CPU参与,而为了便于CPU参与,一定要能够先将数据移动到内存当中。
- 所以在特定时间内,数据一定是磁盘中有,内存中也有。后续操作完内存数据之后,以特定的刷新策略,刷新到磁盘。而这时,就涉及到磁盘和内存的数据交互,也就是IO了。而此时IO的基本单位就是Page。
- 为了更好的进行上面的操作,MySQL服务器在内存中运行的时候,在服务器内部,就申请了被称为Buffer Pool的的大内存空间,来进行各种缓存。其实就是很大的内存空间,来和磁盘数据进行IO交互。
- 为何更高的效率,一定要尽可能的减少系统和磁盘IO的次数
2.索引的结构
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,主要包含以下几种:
索引结构 | 描述 |
---|---|
B+Tree | 最常见的索引类型,大部分引擎都支持B+树索引 |
Hash | 底层数据结构是用哈希表实现,只有精确匹配索引列的查询才有效,不支持范围查询 |
R-Tree(空间索引) | 空间索引是 MyISAM 引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少 |
Full-Text(全文索引) | 是一种通过建立倒排索引,快速匹配文档的方式,类似于 Lucene, Solr, ES |
不同的存储引擎对于索引结构的支持情况
索引 | InnoDB | MyISAM | Memory |
---|---|---|---|
B+Tree索引 | 支持 | 支持 | 支持 |
Hash索引 | 不支持 | 不支持 | 支持 |
R-Tree索引 | 不支持 | 支持 | 不支持 |
Full-text | 5.6版本后支持 | 支持 | 不支持 |
注意:平常所说的索引,如果没有特别指明,都是指B+树结构组织的索引。
a.关于hash索引,B树索引,B+树索引的特点
B树:
- B树节点,既有数据,又有Page指针
- 关键字集合分布在整颗树中;
- 搜索有可能在非叶子结点结束;
B+树
- 所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;
- 不可能在非叶子结点命中;
- 非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;
- 每一个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的范围遍历。
- MySQL 索引数据结构对经典的 B+Tree 进行了优化。在原 B+Tree 的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的 B+Tree,提高区间访问的性能(双向链表)。
HASH
- Hash索引只能用于对等比较(=、in),不支持范围查询(betwwn、>、<、...)
- 无法利用索引完成排序操作
- 查询效率高,通常只需要一次检索就可以了,效率通常要高于 B+Tree 索引
b.为什么使用InnoDB 存储引擎选择使用 B+Tree 索引结构?
- 链表?线性遍历
- 二叉搜索树?退化问题,可能退化成为线性结构
- AVL&&红黑树?虽然是平衡或者近似平衡,但是毕竟是二叉结构,相比较多阶B+,意味着树整体过高,大家都是自顶向下找,层高越低,意味着系统与硬盘更少的IO Page交互。虽然你很秀,但是有更秀的。
- Hash?官方的索引实现方式中,MySQL是支持HASH的,不过InnoDB和MyISAM并不支持.Hash跟进其算法特征,决定了虽然有时候也很快(O(1)),不过,在面对范围查找就明显不行
- 对于 B-Tree,节点不存储data,这样一个节点就可以存储更多的key。可以使得树更矮,所以IO操作次数更少。叶子节点相连,更便于进行范围查找
3.聚簇索引和非聚簇索引
数据库表的索引从数据存储方式上可以分为聚簇索引和非聚簇索引两种。“聚簇”的意思是数据行被按照一定顺序一个个紧密地排列在一起存储。我们熟悉的InnoDB和MyISAM两大引擎,InnoDB的默认数据结构是聚簇索引,而MyISAM是非聚簇索引。
最直观的区别是反映在数据存储方式上,在MySQL数据库中InnoDB(聚簇)和MyISAM (非聚簇)数据存储文件格式如下:
存储引擎是InnoDB, 在data目录下会看到2类文件:.frm、.ibd
(1)*.frm--表结构的文件。 (2)*.ibd--表数据文件
存储引擎是MyISAM, 在data目录下会看到3类文件:.frm、.myi、.myd
(1)*.frm--表定义,是描述表结构的文件。 (2)*.MYD--"D"数据信息文件,是表的数据文件。 (3)*.MYI--"I"索引信息文件,是表数据文件中任何索引的数据树
聚簇索引(Clustered Index)并不是一种单独的索引类型,而是一种数据存储方式。当表有了聚簇索引的时候,表的数据行都存放在索引树的叶子页中。无法把数据行放到两个不同的地方,所以一张表只允许有一个聚簇索引。InnoDB的聚簇索引实际上是将索引和数据保存中同一个B-Tree中。InnoDB通过主键聚集数据,如果没有定义主键,InnoDB会选择一个唯一的的非空索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。
非聚簇索引(NoClustered Index)其中,MyISAM最大的特点是,将索引Page和数据Page分离,也就是叶子节点没有数据,只有对应数据的地址。
下图为MyISAM表的主索引,Col1为主键。
辅助(普通)索引
当然,MySQL除了默认会建立主键索引外,我们用户也有可能建立按照其他列信息建立的索引,一般这种索引可以叫做辅助(普通)索引。
对于MyISAM,建立辅助(普通)索引和主键索引没有差别,无非就是主键不能重复,而非主键可重复。下图就是基于MyISAM的Col2建立的索引,和主键索引没有差别
InnoDB建立辅助(普通)索引,我们以上表中的Col3建立对应的辅助索引如下图:
可以看到,InnoDB的非主键索引中叶子节点并没有数据,而只有对应记录的key值。
所以通过辅助(普通)索引,找到目标记录,需要两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。这种过程,就叫做回表查询为何InnoDB针对这种辅助(普通)索引的场景,不给叶子节点也附上数据呢?原因就是太浪费空间了。
三.MySQL索引的操作
索引的操作这边就不写.........
最后补充一下索引按功能的分类
在MySQL数据库,将索引的具体类型主要分为以下几类:主键索引、唯一索引、常规索引、全文索引。
注意: 当对文章字段或有大量文字的字段进行检索时,会使用到全文索引。MySQL提供全文索引机制,但是有要求,要求表的 存储引擎必须是MyISAM,而且默认的全文索引支持英文,不支持中文。 如果对中文进行全文检索,可以使用sphinx的中文版(coreseek)。
分类 含义 特点 关键字 主键索引 针对于表中主键创建的索引 默认自动创建,只能有一个 PRIMARY 唯一索引 避免同一个表中某数据列中的值重复 可以有多个 UNIQUE 常规索引 快速定位特定数据 可以有多个 全文索引 全文索引查找的是文本中的关键词,而不是比较索引中的值 可以有多个 FULLTEXT