数据库索引
MySQL官方定义:
索引是帮助MySQL高效获取数据的有序数据结构。在数据库之外,数据库系统还维护着满足特定查找算法的数据结构,这样的数据结构已某种方式指向数据,这样就可在这些数据结构上实现高级查找算法,这种数据结构叫做索引。
示意图:
左边是数据表,一共两列七条记录,最左边的是数据记录的物理地址。为了加快Col2查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据的记录物理地址的指针,这样就可以运用二叉查找快速获取到相应的数据。
索引本身也很大,不会全部存储到内存中,索引往往以索引文件的形式存储在磁盘上,索引是数据库中用来提高性能的最常用的工具。
以空间换时间:
索引,ElasticSearch,Redis,缓存(浏览器缓存,JVM缓存,Redis缓存)...
索引有利于查询,不利于增删改..
索引优略势
类似于书籍的目录索引,提高数据检索,降低IO成本
通过索引列队数据进行排序,降低数据排序的成本,降低CPU的消耗
劣势:
实际上索引也是一张表,该表中保存了主键与索引字段,并指向实体类的记录,所以索引也占有空间
虽然索引提高了查询效率,同时也降低了更新表的速度,如对表进行INSERT,UPDATE,DELETE.因为更新表时,MySQL不仅要保存数据,还要保存索引文件每次更新添加了索引列字段,都会调整因为更新所带来的键值变化后的索引信息。
CRUD CREATE READ(使用最频繁) UPDATE DELETE
常见的索引
索引是在MySQL的存储引擎层实现的,并不是在服务器层实现的。所以每种存储引擎的索引都不一定完全相同,也不是所有的存储引擎都支持所有的所有类型。
MySQL提供了四种索引:
-
BTREE 索引:最常见的索引,大部分索引都支持B树索引。
-
HASH 索引:只有Memory引擎支持,使用常见简单。
-
R-tree 索引(空间索引):空间索引MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通用使用较少。
-
Full-text(全文索引):全文搜索也是MyISAM的一个特殊索引类型,主要是用去全文索引,InnoDB从MySQL5.6开始支持全文索引。
我们常说的索引,如果没有特别指明,都是指B+树(多路搜索树,并不一定时二叉的)结构组织的索引。其中聚集索引,复合索引,前缀索引,唯一索引默认都是使用B+Tree 索引。
索引结构
1 BTree
BTree又叫多路平衡搜索树,一颗x叉的BTree特性如下:
-
每个树节点中最多包含x个孩子
-
除根节点与叶节点外,每个节点至少有[ceil(m/2)]个孩子(ceil 向上取整)
-
若根节点不是叶节点,至少有两个孩子。
-
所有的叶子节点都在同一层。
-
每个非叶子节点由n个key与n+1个指针组成,其中[ceil(x/2)-1]<= n <= m-1
这就是个5叉的BTree,BTree树和二叉树相比,查询数据的效率更高,因为对于相同的数据量来说,BTree的层级结构比二叉树小,因此搜索速度快。所以不是所有的二叉树都比BTree搜索速度更快。
2 B+Tree
B+Tree 是B树的变种,查询性能比B树更高。x阶的B+Tree特征:
-
有m个子树的节点包含x个元素(B-Tree中式x-1)
-
根节点和分支节点中不保存数据,只用于索引,所有数据都保存在叶子节点中。
-
所有分支节点和根节点都同时存在于节点中,在子节点元素中是最大或者最小的元素。
-
叶子节点会包含所有的关键字,以及指向数据记录的指针,并且叶子节点本身是根据关键字的大小从小到大顺序链接。
红点表示是指向卫星数据的指针,指针指向的是存放实际数据的磁盘页,卫星数据就是数据库中一条数据记录。
叶子节点中还有一个指向下一个节点的next指针,所以叶子节点形成了一个有序的链表,方便遍历B+树
B+树的优势
1 更高效率的单元查找。
第一次磁盘IO
第二次磁盘IO
第三次IO
貌似这个过程看来,没有与B树的查询过程没有什么区别,但实际上有两点不一样:
B+树的中间节点不存储卫星数据,所以同样大小的磁盘页可以容纳更多的节点元素,这样的话,相同数量的数据下,B+树就相对来说更加矮胖些,磁盘IO的次数更少。
B+树更加稳定,B+树每次查询都要查询到叶子节点,B树每次查询最好情况是根节点,最差是叶子节点。
2 叶子节点形成有顺链表,范围查找性能更优
B树范围查找3-8的过程
先查找3
再查找4、5、6、7、8,中间过程省略,直接到8的查找 这里查找的范围跨度越大,则磁盘IO的次数越多,性能越差。
B+树范围查找3-11的过程
先从上到下找到元素3,然后通过链表指针,依次遍历查找元素568911;如此一来,就不用向B树那样一个个元素进行查找!
B+树优点总结:
单节点可以存储更多的元素,使得查询磁盘IO次数更少
所有查询都要查找到叶子节点,查询性能稳定
所有叶子节点形成有序链表,便于范围查询
MySQL中的B+Tree
MySQL索引数据结构对经典的B+Tree进行了优化,在原有的B+Tree的基础上,增加一个指向相邻叶子节点的链表指针。就形成了带有顺序指针的B+Tree,提高了区间访问的性能!
MySQL中的 B+Tree 索引结构示意图:
索引分类
-
单值索引:即一个索引值包含单个例,一个表可以有多个单例索引。
-
唯一索引:索引列的值必须唯一,但允许有空值。
-
符合索引:即一个索引包含多个列
-
全文索引。
指向相邻叶子节点的链表指针:提高区间风闻的性能!
叶子节点形成链表,便于范围查询!
索引设计原则
索引的设计可以遵循一些已有的原则,创建索引的时候尽量考虑符合这些原则,便于提升索引的使用效率,更高效的使用索引。
1 对查询频次较高,且数据比较大的表建立索引。
2 索引字段的选择,最佳候选列应当从where子句的条件中提取,如果where子句中的组合比较多,应当挑选最常用,过滤效果最好的列的组合。
3 使用唯一索引,区分读越高,使用索引的效率越高,电话号码,邮箱。
4 索引可以有效的提升查询数据的效率,但索引数量不是多多益善,索引越多,维护索引的代价 自然也就水涨船高。对于插入、更新、删除等DML操作比较频繁的表来说,索引过多,会引入 相当高的维护代价,降低DML操作的效率,增加相应操作的时间消耗。另外索引过多的话, MySQL也会犯选择困难病,虽然最终仍然会找到一个可用的索引,但无疑提高了选择的代价。
5 使用短索引,索引创建之后也是使用硬盘来存储的,因此提升索引访问IO效率。
6 利用最左前缀,N个列组合而成的组合索引,相当于创建了N个索引,如果查询时where子句使 用了组成该索引的前几个字段,那么这条查询SQL可以利用组合索引来提升查询效率。
所以具体的SQL语句,添加何时的索引。