索引分为主键索引、唯一索引、普通索引、聚集索引、全文索引几种,而索引其实就是在无序的数据中建立索引,每次查询可以根据索引迅速查到我们想要的数据(就像字典的目录a-z一样)
优点
缺点
数据列不允许重复,不允许为NULL,可以被引用为外键,一个表只能有一个主键索引
数据列不允许重复,允许为NULL值,不可以被引用为外键,一个表允许多个列创建唯一索引
基本的索引类型,没有唯一性限制,允许为NULL值,不可以被引用为外键,一个表可以有多个普通索引
索引类型 | 数据是否允许重复 | 是否允许NULL | 是否可以当作外键 | 索引个数限制 |
---|---|---|---|---|
主键索引 | 否 | 否 | 是 | 仅有一个 |
唯一索引 | 否 | 是 | 否 | 允许多个 |
普通索引 | 是 | 是 | 否 | 允许多个 |
表中可以看出约束是从高到低,对比表种内容然后依据不同场景进行使用
在聚集索引中,表中数据行的物理位置与逻辑值(索引和数据为同一个文件)的顺序
相同,一个表中只能包含一个聚集索引,因为物理顺序只能有一个。聚集索引通常提供更快的数据访问速度。
其中 InnoDB采用的就是聚簇索引,数据和索引文件为一个idb文件
,表数据文件本身就是主索引,相邻的索引临近存储。 叶节点data域保存了完整的数据记录(数据[除主键id外其他列data]+主索引[索引key:表主键id])。 叶子节点直接存储数据记录,以主键id为key,叶子节点中直接存储数据记录。(底层存储结构: frm -表定义、 ibd: innoDB数据&索引文件)
(1)如果表定义了主键,则PK就是聚集索引;
(2)如果表没有定义主键,则第一个非空唯一索引(not NULL unique)列是聚集索引;
(3)否则,InnoDB会创建一个隐藏的row-id作为聚集索引;
索引和数据分开的索引
。
其中MyISAM底层采用的就是非聚簇索引,使用myi索引文件和myd数据文件分离
,索引文件仅保存数据记录的指针地址。叶子节点data域存储指向数据记录的指针地址。(底层存储结构: frm -表定义、 myi -myisam索引、 myd-myisam数据)
所谓覆盖索引就是指索引中包含了查询中的所有字段,这种情况下就不需要再进行回表查询了
MySQL 中只能使用 B-Tree 索引做覆盖索引,因为哈希索引等都不存储索引的列的值,覆盖索引对于 MyISAM 和 InnoDB 都非常有效,可以减少系统调用和数据拷贝等时间
使用多个列来组成一个索引,比如B-Tree的方式
主要用于海量数据的搜索,比如淘宝、京东对商品的搜索就可以建立全文索引(不可能用like模糊匹配吧),这个类型在mysql5.6开始支持InnoDB引擎的全文索引,功能没有专业搜索引擎比如solr、es丰富,如果需求简单,可以使用全文索引
适用场景:适用于海量数据的关键字模糊搜索,比如简易版的搜索引擎
InnoDB使用的是B-Tree算法,即每个叶子节点包含指向下一个叶子节点的指针,就像一个树一样
工作原理:B-Tree索引中,联合索引中的索引项会先根据第一个索引列进行排序,第一个索引列相同的情况下,会再按照第二个索引列进行排序,依次类推。
可以应用到B-Tree索引的情况:
无法使用到B-Tree索引的情况:
如果在列上建立索引,则针对每一行数据,存储引擎会根据所有的索引列计算出一个哈希码,每一个行计算出的哈希码会组成一个哈希表,同时在哈希表中存储了指向每个数据行的指针。
哈希表结构如下:
适用场景:仅作等值匹配且数据重复率低且对索引查找速度要求高的情况
可以应用到哈希索引的情况:
无法使用到哈希索引的情况:
其中,还有一个叫做“自适应哈希索引”,是当InnoDB注意到某些索引的使用频率很高时,会在B-Tree索引之上再建立一层哈希索引,以提高查询效率
空间索引可用于地理数据存储,它需要GIS相关函数的支持,由于MySQL的GIS支持并不完
善,所以该索引方式在MySQL中很少有人使用。
如果 select 所需获得列中有大量的非索引列,索引就需要到表中找到相应的列的信息,这就叫回表
比如如下例子,先使用普通索引查询除出ID,然后再去聚簇索引查询具体数据的过程就叫左做回表
如何避免回表?
使用聚集索引(主键或第一个唯一索引)就不会回表,普通索引就会回表
比如select id, name, sex from user;
,将单列索引(name)升级为联合索引(name, sex),即可避免回表,因为要查询的name和sex都在索引中了
MySQL 5.6引入了索引下推优化,可以在索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表字数
select * from tuser where name like '张 %' and age=10 and ismale=1;
没有索引下推:首先根据索引来查找记录,然后再根据where条件来过滤记录(回表)
有索引下推:MySQL会在取出索引的同时,判断是否可以进行where条件过滤再进行索引查询(回表)
如图所示,有三个事务同时插入同一个记录,导致唯一索引冲突的过程:
死锁发生过程:
根本原因:
唯一索引导致,本质是并发请求导致一个数据重复插入或是网络抖动造成
解决方案: