1、 引言
概要mysql
(1) innodb索引类型与B+树算法
(2) 索引使用注意事项sql
(3) 车点评业务表索引优化案例数据库
问题缓存
(1) InnoDb索引为何要用b+树?性能
(2) 汇集索引与普通索引有什么区别?优化
(3) 为何主键最好是自增?spa
(4) 组合索引有什么优点?指针
(5) 有哪些实际业务场景索引搞不定? 索引
2、 innodb索引类型与B+树
INNODB主要有几种索引:B+树索引,自适应哈希索引,全文索引 ,覆盖索引。
B+树索引是一种多叉平衡查找树。
自适应哈希索引是mysql对于频繁查询的数据采起的hash存储优化,用户没法选择设置。
全文索引主要用于全文检索使用。
覆盖索引说的是查询的字段都属于同一个索引字段,这样效率很是高。
查找树
查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced Binary Search Tree),红黑树(Red-Black Tree ),B-tree/B+-tree/ B*-tree (B~Tree)。前三者是典型的二叉查找树结构,其查找的时间复杂度O(log2N)与树的深度相关,那么下降树的深度天然会提升查找效率。
B树/B+树/B*树
B树
B+树
全部的叶子结点中包含了所有关键字的信息,及指向含有这些关键字记录的指针,且叶子结点自己依关键字的大小自小而大的顺序连接。
数据库索引采用B+树的主要缘由是: B树在提升了磁盘IO性能的同时并无解决元素遍历的效率低下的问题。正是为了解决这个问题,B+树应运而生。B+树只要遍历叶子节点就能够实现整棵树的遍历。并且在数据库中基于范围的查询是很是频繁的,而B树不支持这样的操做(或者说效率过低)。
B*树
和B+树的主要区别:
一、B*树中非根和非叶子结点都有指向兄弟的指针;
二、B*树定义了叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2)
汇集索引和普通索引
一、主键和普通索引都是B+树索引
二、主键的叶子节点是:数据;普通索引的叶子节点是:主键的值
三、普通索引的检索须要通过两次B+树查找:
I)经过普通索引,找到:主键key
II)经过主键key,查找到元素
自适应hash索引
Innodb存储引擎会监控对表上二级索引的查找,若是发现某二级索引被频繁访问,二级索引成为热数据,创建哈希索引能够带来速度的提高。常常访问的二级索引数据会自动被生成到hash索引里面去(最近连续被访问三次的数据),自适应哈希索引经过缓冲池的B+树构造而来,所以创建的速度很快。
自适应hash索引只适用于等值查询。
INNODB如何创建汇集索引
1)有主键,则INNODB使用它做为汇集索引。
2)未定义主键,INNODB选第一个非NULL的惟一索引列,使用它做为汇集索引。
3)若是1)、2)都没有,Mysql自动添加一个不可见不可引用的6byte大小的rowid做为汇集索引.
主键必须是自增
若是表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页
若是使用非自增主键(若是身份证号或学号等),因为每次插入主键的值近似于随机,所以每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增长了不少开销,同时频繁的移动、分页操做形成了大量的碎片,获得了不够紧凑的索引结构,后续不得不经过OPTIMIZE TABLE来重建表并优化填充页面。
普通索引的叶子节点内容
存储的是主键的值。好处以下
辅助索引使用主键做为"指针" 而不是使用地址值做为指针的好处是,减小了当出现行移动或者数据页分裂时辅助索引的维护工做,使用主键值看成指针会让辅助索引占用更多的空间,换来的好处是InnoDB在移动行时无须更新辅助索引中的这个"指针"。
普通索引的叶子节点空洞
B*树定义了叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3
B+树的最低使用率是1/2,这是由树的分裂算法决定的。
B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增长新结点的指针;
B*树的分裂:当一个结点满时,若是它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(由于兄弟结点的关键字范围改变了);
若是兄弟也满了,则在原结点与兄弟结点之间增长新结点,并各复制1/3的数据到新结点,最后在父结点增长新结点的指针;
因此,B*树分配新结点的几率比B+树要低,空间使用率更高;
每一次数据页分裂,都会致使叶子节点空洞的产生。
COUNT查询较慢缘由以及优化
count指令实现上采用实时统计方式,要么经过汇集索引统计,要么经过二级索引统计
在无可用的二级索引状况下,执行count会使MySQL扫描全表数据,当数据中存在大字段或字段较多时候,其效率很是低下(每一个页只能包含较少的数据条数,须要访问的物理页较多)
二级索引存储的数据为指定字段的值与主键值。当咱们经过二级索引统计数据的时候,无需扫描数据文件;
因此,能够创建合适的单子段普通索引,提升COUNT统计效率
组合索引优点
(1) 知足最左前缀的查询,均可以用到索引。
(2) 覆盖索引查询,效率更快。
3、 索引使用注意事项
(1) 尽可能选择区分度高的列做为索引。
区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大咱们扫描的记录数越少,惟一键的区分度是1
(2) 选用自增ID做为主键。
(3) 组合索引的创建须要进行仔细分析;
1)、正确选择组合索引中的主列字段,通常是选择性较好的字段;
2)、组合索引的几个字段是否常常同时以AND方式出如今Where子句中?
若是是,则能够创建复合索引;不然考虑单字段索引;
3)、若是复合索引中包含的字段常常单独出如今Where子句中,则分解为多个单字段索引;
4)、若是复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减小复合的字段;
(4) 频繁进行数据操做的表,不要创建太多的索引;
(5) 删除无用的索引,避免对执行计划形成负面影响;
(6) 应尽可能避免在WHERE子句中对字段进行NULL值判断,不然将致使引擎放弃使用索引而进行全表扫描。
(7) 字符字段只建前缀索引, 最好不要作主键。
(8) 使用同类型进行比较, 不然不会用到索引。
(9) 尽可能避免在WHERE子句中使用!= 或 <>,not like 操做符,不然将引擎放弃使用索引而进行全表扫描。
(10) 索引不会包含有NULL值的列。
(11) 单表索引建议控制在5个之内。
(12) 何时不要使用索引?
常常增删改的列不要创建索引.
有大量重复的列不创建索引.
表记录太少不要创建索引;
...