索引
1. 索引是一种数据结构,基于数据库表创建,包含一个表中某些列的值以及记录对应的地址,目的是为了优化查找速度。
2. 索引结构的实现方式:
- 二叉查找树,红黑树:相对于B族树而言,深度高,逻辑相邻的节点实际存储可能分散很远,需要多次IO读取,效率低。
- B树:每个节点大小设计为一页,一次IO能全部读取,充分利用了磁盘预读。深度低,IO次数少。
- B+树:叶子节点包含所有的节点,支持叶子顺序遍历,方便范围查找。非叶子节点没有指向数据的引用,故一个节点可以存储更多的关键字。
- HashMap: 将键值换算为哈希值,等值查询下速度非常快,但是范围查询(模糊查询)就毫无用武之地了,另外,在大量重复键值的情况下,效率非常低。
关于B树结构的不同,详细请参考:https://blog.csdn.net/mine_song/article/details/63251546
关于HashMap和B数索引的区别:http://imysql.com/2016/01/06/mysql-faq-different-between-btree-and-hash-index.shtml
3. 聚集索引/非聚集索引
聚集索引:索引列排列的逻辑顺序和数据行的物理存储顺序一致,一个表中只能有一个聚集索引,叶子节点是数据节点。类似于字典中的拼音查询,适合范围查询。
非聚集索引:不满足聚集索引条件的其他索引,一个表可以有多个非聚集索引,类似于字典中的部首查询。
4. 非聚集索引的二次查询
非聚集索引叶子节点依然是索引节点,只是有一个指针指向对应的数据块。当查询包含不在索引中的列时,需要进行第二次查询以找到对应的数据。
#非聚集索引username select username, score from t_student where username = '小明';
解决方法:使用复合索引,建立两列以上的索引。
详细请参考:https://www.cnblogs.com/aspnethot/articles/1504082.html
3. MySQL索引的实现
针对不同的存储引擎,索引的实现方式是不同的,一下介绍 MyISAM 和 InnoDB 两个存储引擎的实现。
1. MyISAM使用B+树作为索引结构,叶子节点的data域存放的是数据记录的地址。
1)主键索引(Col1)
2)辅助索引(Col2)
在MyISAM中,主索引和辅助索引在结构上没有区别,唯一不同的是主索引要求key唯一,辅助索引可以重复。MyISAM的索引方式是非聚集的。
2. InnoDB索引同样使用B+树
1)主键索引(叶子节点包含完整数据记录,是聚集索引)
2)辅助索引(引用主键作为data域,是非聚集索引,使用辅助索引查询需要两遍检索:获得主键+在主键中获得数据)
4. 最左前缀原理
https://www.cnblogs.com/big-handsome-guy/p/7755059.html
创造联合索引时(emp_no, title, from_date),上表存在主键索引emp_no(index 1), title(index 2), from_date(index 3)。查询语句按照最左前缀原理,按照index顺序从1开始往后使用连续的一段索引,如果中间缺少某个索引,则之后的索引都不会用到(除非额外添加辅助索引)。
存在一下几种情况:
- 全列匹配:按照索引中所有列精确匹配("="/"IN"),索引可以被用到,且会自动优化顺序
- 最左前缀匹配:查询语句精确匹配索引锁边连续的一个/多个列时,只用到一部分
- 中间某条件未提供:之后的索引均不会被用到,可以使用辅助索引连接断开的两端或者使用“隔离化”优化方法
- 没有指定第一列:所有索引均不会用到
- 匹配某列的前缀字符串:通配符%不能出现在开头
- 范围查询:范围列可以用到索引(必须是最左前缀),且只能用于一个范围列,范围列之后的列无法用到索引(是建立索引时的顺序而不是查询顺序!!)。
- 查询语句中含有函数或表达式:该列不使用索引
那么为什么会遵循最左匹配原理呢?
以B+树作为索引来理解,建立联合索引时靠左边的索引在树的节点位置中靠上,而查找时是按照节点从上到下的顺序进行的,所以会有最左匹配原则。
5. 索引选择性和前缀索引
索引本身需要存储空间,其次,数据的插入删除修改也需要更新索引,一般下面两种情况不建议使用索引:
- 表的记录较少,此时直接全表扫描
- 索引的选择性(不重复的索引值/表记录数)较低
- 文本格式的字段
InnoDB主键索引建议设定自增,减少索引的维护。
在下面几种情况下,推荐添加索引:
1. 经常需要搜索的列
2. 作为主键的列
3. 经常需要范围搜索的列
4. 经常需要排序的列
参考:http://blog.codinglabs.org/articles/theory-of-mysql-index.html