Mysql 索引
索引存在的目的就是为了加速查询。为了加速查询,索引对数据进行了一系列组织,使数据的存放更有序,类似于书本的目录。也正是因为对数据进行了约束,所以索引会降低更新效率。数据更新时不再是简单的更新数据,而在更新数据之后要将其放在正确的位置。同时索引也会占用磁盘空间。
索引的实现方式
Innodb引擎中索引只有B+树这一种实现方式。为什么选择B+树而不是数组、二叉树、B树,主要是考虑磁盘IO。
Mysql作为一个数据持久化的数据库,所有的数据都是存储在磁盘上的,磁盘的访问性能在计算机的硬件中算是比较慢的,尤其是对于机械硬盘来说,随机访问速度更是慢的离谱,相比较而言,在内存中进行处理速度就快的多。因此想要加速数据查询,首先要做的就是尽可能减少磁盘IO,减少单次查询需要查询的磁盘次数。对于有序数组来说,数据需要进行二分查找,效率与二叉树无异,但是涉及到新增和修改之后的数据移动问题。二叉树在内存中查找效率是log(n),速度很快,但是树的高度也为log(n),如果将树的所有节点存储在磁盘上,则需要访问log(n)次磁盘,当数据量较大时,磁盘访问次数还是太大。
B树和B+树也是搜索树结构,但是相较于二叉树,他们每个节点能够存储多条数据,因此整体树的高度相较于二叉树要低很多。其实树的高度就决定了磁盘访问次数。因此当数据量较大时,B树和B+树的磁盘访问次数要比二叉树少很多,自然效率要更高。
B+树相较于B树有两点优化
- 对于单行记录,B树直接存储在所在的节点上,包括叶子节点和非叶子节点。但是B+树只存在叶子节点,非叶子节点只存储一个索引值。假如B树和B+树每个节点的大小一致的话,对于非叶子节点来说,B+树存储的记录行数要比B树多,因此B+树的高度也更低,因此磁盘IO数量也更少,查询效率更高。
- B+树的所有叶子节点使用链表结构相连。因此B+树进行范围查询时,只需要查到一个边界值,便可以直接遍历链表查询。而B树则只能挨个查询。
Mysql的Memory引擎,支持在内存中建表。memory引擎的主键索引使用哈希索引。哈希索引单值查询效率高O(1),但是当数据量大时,哈希碰撞严重也会导致查询效率下降,同时哈希索引也无法支持范围查找。
InndoDb中的索引组织形式
Innodb中的索引分为主键索引(聚簇索引)和非主键索引(非聚簇索引)。主键索引的叶子节点存放当前记录的所有字段信息,非主键索引的叶子节点存放索引字段值和主键值。因此假如查询经过非主键索引,需要经过回表的过程,也就是拿到主键值之后去主键索引中查询需要的字段值。Mysql为了减少不必要的回表,当查询所使用的非主键索引中已包含了所需查找的所有字段时就无需回表直接返回。这个过程被称为覆盖索引。在实际应用中尽可能使用覆盖索引也是一种常见的优化手段。
为什么主键一般要求自增
当我们新增数据时,可能会导致B+树节点数据过多而需要将其分裂成两个节点。当我们删除数据时,可能会导致B+树节点数据量过小,而需要与旁边的节点进行合并。如果主键是一直递增的话,当新数据插入时只会将数据写入到最后的叶子节点上,当节点装不下之后开启新的节点,不会涉及到叶子节点的分裂。
同时使用自增数字,一般所占用的位数较小,bigint 8个字节。主键越小,非主键索引的叶子节点就越小,普通索引占用的空间就越小。