索引是帮助MySQL 高效获取数据的排好序的数据结构。html
MySQL 默认使用的是B+Tree数据结构。数据库
在介绍结构以前,先简单说下磁盘的读取原理:数据结构
操做系统读写磁盘的基本单位是扇区,而文件系统的基本单位是簇(Cluster)。并发
MySQL在存储数据时数据都存储在磁盘的一道道扇区中,磁盘是旋转的,每次存储的数据可能会存储在不一样的扇区中。高并发
在读取时,磁道每次须要先进行寻道操做(速度慢),磁头只能进行左右移动,每一次寻道都是一次I/O操做。性能
若是数据都存在同一磁道中,那么旋转磁盘(速度快)就能够取到数据,不须要进行寻道操做,会大大减小开销。网站
(这里是我本身的理解,若是有不对的地方,欢迎你们指出来)操作系统
给你们推荐一个数据结构可视化网站,能够直观的演示各类结构3d
若是普通的一颗二叉树,在极端状况下会退化成链表结构。如图: 指针
和二叉树同样,在数据量大的状况下,树的深度太大,查询次数太高。
好比,有500W的数据,假如树的高度有20层,你要查询的数据恰好在叶子节点,那么须要进行20次寻道操做,和磁盘进行20次I/O交互操做,大大加大了开销。
HASH索引,相比较于B-Tree 而言,不须要从根节点到叶子节点的遍历,能够一次定位到位置,查询效率更高,但缺点也很明显:
仅能知足全值查询,不能使用范围查询。由于是经过HASH值进行计算,HASH值是没规律的,因此只能精确查询,不能保证顺序和原来一致,因此不行进行范围查询。
不能进行排序,缘由如上。
HASH碰撞。
B+Tree 是平衡树的一种,而且全部叶子节点位于同一层,是不会退化成链表结构的。
B+Tree 有一个度的概念,指节点的数据存储个数。度越大,节点保存的数据个数就越多。那么相应的树的高度下降,在进行查询时,须要进行的I/O操做更少,读取数据的速度更快。
非叶子节点不存储data,只存储key,能够增大度。叶子节点只存储data, 不存储指针,顺序访问指针,能够提升区间访问的性能。
进行查找操做时,首先在根节点进行二分查找,找到一个key所在的指针,而后递归的在指针所指向的节点进行查找。直到查找到叶子节点,而后在叶子节点上进行二分查找,找出 key 所对应的 data。
通常使用磁盘I/O次数评价索引结构的优劣
预读:磁盘通常会顺序向后读取必定长度的数据(页的整数倍)放入内存。
局部性原理:当一个数据被用到时,其附近的数据也一般会立刻被使用。
B+Tree 节点的大小设为等于一个页,每次新建节点直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,就实现了一个节点的载入只需一次I/O。
B+Tree 的度通常会超过100,所以高度很是小(通常为3到5之间)
MyISAM 索引文件和数据文件是分离的。
MyISAM 引擎使用B+Tree 做为索引结构,MyISAM的索引文件仅仅保存数据记录的地址。
MyISAM中,主索引和辅助索引在结构上没有任何区别,只是主索引要求key是惟一的,而辅助索引的key能够重复。
数据文件自己就是索引文件。
InnoDB 引擎也使用B+Tree 做为索引结构,叶节点包含了完整的数据记录。
InnoDB的数据文件自己要按主键汇集,因此InnoDB要求表必须有主键(MyISAM能够没有)。
InnoDB中,主键索引包含了完整的数据记录,而辅助索引都引用主键做为data域。
知道了InnoDB的索引实现后,就明白了为何不建议使用过长的字段做为主键了,由于全部辅助索引都用主索引,过长的主索引会令辅助索引变得过大。
事物:InnoDB支持事务,可使用 Commit 和 Rollback 语句。MyISAM不支持。
并发:MyISAM 只支持表级锁,而InnoDB 还支持行级锁。
外键:InnoDB 支持外键,MyISAM不支持。
备份:InnoDB 支持在线热备份,MyISAM不支持。
崩溃恢复:MyISAM 崩溃后发生损坏的几率比 InnoDB 高不少,并且恢复的速度也更慢。
其它特性:
InnoDB是汇集索引,MyISAM是非汇集索引。
InnoDB不保存表的具体行数,MyISAM用变量保存了整个表的行数。
InnoDB不支持全文索引,MyISAM支持全文索引。
MyISAM 支持压缩表和空间数据索引。
主键索引:是一种特殊的惟一索引,不容许有空值。设定为主键后数据库会自动创建索引innodb为汇集索引。
惟一索引:索引列中的值必须是惟一的,可是容许为空值。
单值索引:索引只包含单个列,但一个表中能够有多个单值索引。
复合索引:在表中的多个字段组合上建立的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀原则。
全文索引:只有在MyISAM引擎上才能使用,只能在CHAR、VARCHAR、TEXT类型字段上使用全文索引,在一堆文字中,经过其中的某个关键字等,就能找到该字段所属的记录行。好比有"怡红院、金凤楼"等等,能够 经过金凤楼,可能就能够找到该条记录。
空间索引:只有在MyISAM引擎上才能使用,建立空间索引的列,必须将其声明为NOT NULL。空间索引是对空间数据类型的字段创建的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在建立空间索引时,使用SPATIAL关键字。
B+Tree 是按照第一个关键字进行索引,而后在叶子节点上按照第一个关键字、第二个关键字、第三个关键字…进行排序。使用复合索引的时候,会根据你的索引顺序,从左开始匹配。
索引只能用于查找key是否存在(相等),遇到范围查询(>、<、between、like左匹配)等就不能进一步匹配了,后续退化为线性查找。
提升查询效率(下降IO使用率)。
下降CPU使用率, 例如:...order by age desc
,由于B+Tree 索引自己就是一个排好序的结构,所以在排序时能够直接使用。
索引自己很大,实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,因此索引列也是要占用空间。
索引会下降增删改的效率,MySQL不只要保存数据,还要保存一下索引文件每次更新添加了索引列的字段, 都会调整由于更新所带来的键值变化后的索引信息。
索引不是全部状况均适用:A. 少许数据 B.频繁更新的字段 C.不多使用的字段
主键自动创建惟一索引。
频繁做为查询条件的字段应该建立索引,WHERE 后面的语句。
查询中与其它表关联的字段,外键关系创建索引。
单键/组合索引的选择问题,who?在高并发下倾向建立组合索引。
查询中排序的字段,排序字段若经过索引去访问将大大提升排序速度。
查询中统计或者分组字段。