MySQL索引
MySQL
在项目开发中是最常用的了,但是对其还不是那么的了解,针对于索引展开学习,详细的学习一下索引到底是什么,有什么作用?为什么要建立索引?等一系列的问题要搞搞清楚。不能用的这么不明不白的。
什么是索引
有关于索引官方是这样介绍的,索引是帮助MySQL
高效获取数据的结构。其实更通俗的来说,MySQL
的索引就好比是一本书前面的目录,能够加快数据的查询速度。
大家应该都用过字典,字典前面有按照拼音查找和按照笔画查找文字,其实这个行为就有些类似于MySQL
的索引了。
一般的来说索引本身的也很大,不可能全部都存储在内存中,因此索引往往也被存储在磁盘的文件中,可能存储在单独的索引文件中,也可能和数据存放在同一个文件中,这种情况依据情况而定。我们通常所说的索引包括聚集索引
,覆盖索引
,组合索引
,前缀索引
,唯一索引
等,默认都是使用B+
树结构组织(多路搜索树,并不一定是二叉树)的索引。
索引分类
关于索引的类型,上面也说了一些,也是蛮多的,但是如何正确的使用索引是个问题,下面一一说一下常用索引的类型有哪些。
单列索引
单列索引其实是一个统称,我是这样理解的,单列索引都包括什么呢?单列索引包括普通索引
、唯一索引
、主键索引
。单列索引是一个索引只包含单个列,但是一个表中可以有多个单列索引。
# 普通索引
MySQL
中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹时为了查询数据更快一点。
普通索引创建方式:
// 方式一
// 在原有表中添加普通索引
ALTER TABLE users ADD INDEX index_users (id)
// 方式二
// 在表中创建普通索引
CREATE INDEX index_name ON table_name (column_name)
# 唯一索引
索引列中的值必须是唯一的,但是允许为空值。
主键索引创建方式:
// 方式一
// 在原有表中添加唯一索引
ALTER TABLE users ADD UNIQUE (id)
// 方式二
// 创建唯一索引,数据不能有重复值
CREATE UNIQUE INDEX index_users ON users (id)
# 主键索引
这是一种比较特殊的唯一索引,不允许有空值,一般是在建表的时候指定了主键,就会创建主键索引(CREATE INDEX不能用来创建主键索引,使用 ALTER TABLE来代替)
主键索引创建方式:
// 在原有表中添加列时标注为主键索引
ALTER TABLE users ADD PRIMARY KEY (id)
组合索引
在表中的多个字段组合上创建索引,组合索引的使用,需要遵循最左前缀原则
,一般情况下,建议使用组合索引代替单列索引。
最左前缀原则
即最左优先,在检索数据时从联合索引的最左边开始匹配,组合索引的第一个字段必须出现在查询组句中,这个索引才会被用到。
组合索引创建方式:
// 创建组合索引
ALTER TABLE article Add INDEX inde_time (title(50),time(10))
单列索引(全文索引)
全文索引只有在 myisam 引擎上才能使用,只能在CHAR
、VARCHAR
、TEXT
类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行。
单列索引(全文索引)创建方式:
// 创建全文索引
CREATE FULLTEXT INDEX index_name ON table(column(length))
alter table table_name add fulltext index_name(column)
索引的优缺点
索引优点:
- 可以提高数据检索效率,减低数据库的
IO
成本,类似书的目录 - 通过索引列对数据进行排序,降低数据的排序成本,降低了CPU的消耗
- 被索引的列会自动进行排序,包括
单列索引
和组合索引
,只是组合索引的排序要复杂一些 - 如果按照索引列的顺序进行排序,对应的
order by
语句,效率就会提高很多 where
索引列在存储引擎层进行处理- 覆盖索引,不需要回表查询
- 被索引的列会自动进行排序,包括
索引缺点:
- 索引会占据内存空间
- 索引虽然会提高查询效率,但是会降低更新表格数据的效率。例如每次对表数据进行增删操作,
MySQL
不仅要保存数据,还要保存和更新对应的索引文件。
索引原理
上文中已经说到过,使用索引的目的是为了提高查询效率,减少IO
的操作成本,其实其原理和使用字典是相类似的。通过不断的缩小想要获取的数据范围来筛选出最终想要的数据结果,同时把随机的事件变成顺序事件,也就是说有了这种索引机制,总是可以使用同一种方法来查找想要的数据。
其实回头想想,数据库其实也是这个样子的,但是其内部实现原理要远远比这个复杂的多,因为在查询数据的时候不光是查询准确的值,有的时候我们可能需要进行范围性的查询。
其实实质上索引也是会存储到磁盘上,这个在上文中已经提到过了,其实索引的存储结构是在存储引擎里面来实现的,换句话来说依据不同的存储引擎会使用不同的索引。
myisam 和 innoDB 的存储引擎只支持B+TREE
,也就是说默认使用的BTREE
,不能够更换。innoDB
和Memory
存储则是是使用的HASH
和BTREE
引擎,HASH
索引通常来说要比BTREE
快。
说到这里才说到正点上,主要介绍一下B+TREE
和BTREE
两者之间的区别以及如何作业的。
# BTREE和B+TREE
在上文中也提到过B+TREE
是一种数据存储引擎,实质上B+TREE
在数据库中的实现是最常见的一种索引形式。接下来就说一下BTREE
和B+TREE
是个什么玩意。假设我们的数据结构如下图所示。
看到图中不相同的数分为0012-0017
,如果我们只看最下面这一层实际上可以看出我们得到的是一个类似于链表结构的数据结构图,通常都会把这部分叫做叶子节点
。
其实BTREE
和B+TREE
最大的区别就是在于,B+TREE
只会在叶子节点中产生所有的数据,BTREE
则会在所有的节点上都会存有数据。如果我们细心观察叶子节点就会发现其内部的数据结构是从右向左从小到大有序排列的。B+TREE
存储的数据是在一行中,并且这些数据都是有指针指向的,也就是有顺序的索引列,这个在上图中可以明显的看出来。
BTREE
的高度一般会在2-4
之间,树的高度越高则直接影响到其IO
速度,因为每次IO
都需要进行频繁的查找。若三层结构的支撑数据结构可以达到20G的话,那么4层树结构则会可以高达几十个T。
# 聚集索引(InnoDB)
聚集索引:聚集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。一个表只能有一个聚集索引,因为一个表的物理顺序只有一种情况,所以,对应的聚集索引只能有一个。如果某索引不是聚集索引,则表中的行物理顺序与索引顺序不匹配,与非聚集索引相比,聚集索引有着更快的检索速度。 ——节选自百度百科
主键索引的叶子节点会存储数据行,也就是说数据和索引是在一起的,这就是聚集索引。辅助索引只会存储主键的值。如果没有主键,则使用唯一索引简历聚集索引,如果没有唯一索引,Mysql
会按照一定规则创建聚集索引。
主键索引
InnoDB
要求表必须有主键,如果没有显式指定主键,则Mysql
系统会自动选择一个可以做唯一表示的数据记录的列作为主键,如果不存在这种列,则Mysql
自动为InnoDB
表生成一个隐含字段作为主键,其类型为长整形。