# 1、索引的语法
创建索引:
- 建表的时候添加索引
- 建表之后添加索引
tips:
索引需要占用磁盘空间,所以在创建索引时要考虑磁盘空间是否足够。
创建索引时要对表加锁,所以实际操作中需要在业务空闲期进行。
2、索引的优缺点
优点:可以快速检索;根据索引分组和排序,可以快速分组和排序。
缺点:
索引本身也是表,所以会占用存储空间。索引表是数据表的1.5倍。
索引表的维护和创建也需要时间。
构建索引表会降低数据表修改的效率,因为修改数据表的同时还要修改索引表。
3、索引的分类
主键索引、唯一索引、普通索引、全文索引、组合索引
- 主键索引:根据主键做索引,不允许重复,不允许空值。
- 唯一索引:用来建立索引的列的值必须是唯一的,允许空值。
- 普通索引:用表中的普通列来建索引,没有任何限制。
- 全文索引:用大文本对象的列构建的索引。
- 组合索引:用多个列组合成的索引,这些列都不能有空值。
4、索引的实现原理
MySQL支持的索引类型:哈希索引,全文索引,BTree索引,B+Tree索引。
- 哈希索引
只有memory(内存)存储引擎支持哈希索引。哈希索引用索引列的值计算该值的hashCode,然后在hashCode相应的位置存储该值所在行数据的物理位置。因为使用散列算法,所以访问速度非常快。但是一个值只能对应一个HashCode,而且是散列的分布方式,所以不支持范围查询和排序。
- 全文索引
可适用与MyISAM和InnoDB两种引擎。对于大对象或较大的CHAR型数据,普通索引会消耗很长的时间。使用全文索引,会对文本生成一份单词的清单,在索引时根据这个单词清单来完成索引。
- BTree索引
BTree是平衡搜索多叉树。每个非叶子结点由n-1个key和n个指针组成,d(度)<=n<=2d,非叶子结点的key都是由[key,data]二元组,key表示作为索引的键,data为键值所在行的数据。
在BTree的机构下,可以使用二分查找的查找方式,查找复杂度为h*log(n),一般来说树的高度是很小的,一般为3左右,因此BTree是一种非常高效的查找结构。
B+Tree索引
B+Tree是BTree的一个变种。
Q/A:B+Tree对比BTree的优点?
磁盘读写代价更低
因为提升查找速度的关键在于尽可能少的磁盘I/O,所以每个结点的key越多,树的高度越小,需要I/O的次数越少。因此B+Tree更快,因为B+Tree的非叶子结点不存储data,可以存储更多的key。
查询速度更稳定
因为B+Tree的非叶子结点不存储数据,所以所有的数据都在叶子结点中查询,所有数据的查询速度是一样的。
带顺序索引的B+Tree
很多存储引擎对B+Tree做了优化,添加了指向相邻叶结点的指针,形成了带有顺序访问指针的B+Tree,这样做是为了提高区间查询的效率,只要找到第一个值那么就可以顺序的查找后面的值。
聚簇索引和非聚簇索引:
存储引擎是怎么实现索引结构的?
MySQL中最常见的两种引擎是MyISAM,InnoDB,分别实现了非聚簇索引和聚簇索引。
聚簇索引:聚簇索引的顺序就是数据的物理存储顺序。
非聚簇索引:索引顺序与数据物理排列顺序无关。
在索引的分类中,可以按照索引的键来分为“主索引”和“辅助索引”,使用主键键值建立的索引称为“主索引”,其他的称为“辅助索引”。因此主索引只有一个,辅助索引有很多个。
聚簇索引的辅助索引的叶子节点的data存储的是主键的值,主索引的叶子节点的data 存储的是数据本身,也就是说数据和索引存储在一起,并且索引查询到的地方就是数据(data)本身,那么索引的顺序和数据本身的顺序就是相同的;
而非聚簇索引的主索引和辅助索引的叶子节点的data都是存储的数据的物理地址,也就是说索引和数据并不是存储在一起的,数据的顺序和索引的顺序并没有任何关系, 也就是索引顺序与数据物理排列顺序无关。
小结:
InnoDB支持事务,支持行级别锁定,支持B-tree、Full-text等索引,不支持hash索引。
MyISAM不支持事务,支持表级别锁定,支持B-tree、Full-text等索引,不支持hash索引。
Memory不支持事务,支持表级别锁定,支持B-tree、hash等索引,不支持full-text索引。
5、索引的使用策略
什么时候使用索引?
- 主键自动建立唯一索引;
- 经常作为查询条件在WHERE或者ORDER BY语句中出现的列要建立索引。
- 作为排序的列要建立索引。
- 查询中与其他表关联的字段,外键关系建立索引。
- 高并发下倾向组合索引。
- 用于聚合函数的列可以建立索引,例如使用了max(column_1)或count(column_1)就需建立索引。
什么时候不要使用索引?
- 经常增删改
- 有大量重复的列
- 表记录太少
索引失效的情况?
组合索引中不能有列的值为null,如果有,那么这一列对组合索引就是失效的。
在一个SELECT语句中,索引只能使用一个,如果在WHERE中使用了,那么ORDER BY就不能使用了。
LIKE操作中,“%aa%”会失效,“aa%”可以使用。
在索引的列上使用表达式或者函数会使索引失效。也就是说,在查询条件中使用正则表达式时,只有在搜索模版的第一个字符不是通配符的情况下才能使用索引。
查询条件下使用IS NULL,IS NOT NULL
字符串不加单引号会导致索引失效,更准确的说是类型不一致会导致失效。