本文是在看极客时间《Mysql实战45讲》时记的笔记,整理下加深理解。mysql
简单来讲,数据库索引就是为了提升数据库查询的效率,就像书的目录同样,能够根据目录快速的找到其中的某一个知识点。sql
简单的介绍下以上三种模型:数据库
==哈希表==是一种以键-值(key-value)存储的数据结构,咱们只要输入待查找的key值,就能够找到其对应的值value,哈希的思路很简单,把值放在数组里,经过一个哈希函数把key换算成一个肯定的位置,而后把value放在数组的这个位置。不可避免的状况下,多个Key值通过哈希运算会出现同一个值的状况,处理这种状况的一种方法是拉出一个链表。数组
因为哈希表内部的排序并非递增的,因此新增元素的时候速度会很快,但缺点是由于不是有序的,因此哈希表作区间查询的速度是很慢的。因此,哈希表这种结构只适用于只有等值查询的场景,好比Memcached以及其余Nosql引擎。性能优化
==有序数组==在等值查询和范围查询场景中的性能都很是优秀。可是在须要更新数据的时候就很麻烦了,若是在中间插入一个记录就必须挪动后面全部的记录,成本过高。因此有序数组只适用于静态存储引擎。数据结构
N叉树在读写上的性能优势,以及适配磁盘的访问模式,已经被普遍应用于数据库引擎中了。数据库设计
不论是哈希仍是有序数组,或者 N 叉树,它们都是不断迭代、不断优化的产物或者解决方案。在咱们内心要有个概念,数据库底层存储的核心就是基于这些数据模型的,每碰到一个新的数据库,咱们都应先关注他的数据模型,这样才能从理论上分析出这个数据库的应用场景。函数
在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。InnoDB使用了B+树索引模型,因此数据都是存储在B+树中的。性能
每个索引在InnoDB里面都对应一颗B+树。优化
假设咱们有一个主键列为ID的表,表中有字段K,并在K上有索引。
这个表的建表语句:
mysql> create table T( id int primary key, k int not null, name varchar(16), index (k))engine=InnoDB;
表中 R1~R5 的 (ID,k) 值分别为 (100,1)、(200,2)、(300,3)、(500,5) 和 (600,6),两棵树的示意图以下:
从图中咱们能够看出来,根据叶子节点的内容,索引分为主键索引和非主键索引。
主键索引的叶子节点存放的是整行的数据,非主键索引的叶子节点存放的是主键的值。
根据上面的索引结构说明,咱们能够得出一个问题,基于主键索引和普通索引的查询区别:
select * from T where ID = 500;
,即主键查询方式,则只须要搜索ID这颗B+树;select * from T where k = 5;
,即普通索引查询方式,则须要先搜索k索引树,获得ID的值为500,再到ID索引树搜索一次,这个过程称为回表。也就是说基于非主键索引查询会多扫描一次索引树。
B+树为了维护索引的有序性,在插入新值的时候须要作必要的维护。
建表时,尽可能保持有自增主键。每次插入一条新记录,都是追加操做,都不涉及到挪动其余记录,也不会触发叶子节点的分裂。
而有业务逻辑的字段作主键,则每每不容易保证有序插入。
同时主键的长度越小,普通索引的叶子节点就越小,普通索引占用的空间就越小。
因此从性能和存储空间来看,自增主键每每是更合理的选择。
若是执行的语句是 select ID from T where k between 3 and 5
,这时只须要查 ID 的值,而ID 的值已经在 k 索引树上了,所以能够直接提供查询结果,不须要回表。也就是说,在这个查询里面,索引 k 已经“覆盖了”咱们的查询需求,咱们称为覆盖索引。
因为覆盖索引能够减小树的搜索次数,显著提高查询性能,因此使用覆盖索引是经常使用的性能优化手段。
第一原则是,若是经过调整顺序,能够少维护一个索引,那么这个顺序每每就是须要优先考虑采用的。
其次考虑的就是空间,好比name 字段是比 age 字段大的 ,那我就建议你建立一个(name,age) 的联合索引和一个 (age) 的单字段索引。
在Mysql5.6以前,只能从最左前缀查询到ID开始一个个回表,到主键索引上找出数据行,再对比字段值。
Mysql5.6以后,引入索引下推的优化,能够在遍历过程当中,对索引中包含的字段先作判断,直接过滤掉不知足条件的记录,减小回表次数。
总之在知足语句需求的状况下,尽可能地减小访问资源是数据库设计的重要原则之一。咱们在使用数据库的时候,尤为在设计表结构时,也要以减小资源消耗为目标。
极客时间《Mysql实战45讲》