索引
索引是什么?索引是一种数据结构,是一种能够帮助我们快速定位到数据的数据结构。最长常见的数据结构有数组、链表、二叉树、红黑树。
数组我们如何定值查询?只能遍历比较了,最差的情况下要遍历所有元素,时间复杂度O(n)。
链表如何定值查找元素?那就更只能靠遍历每一个节点来实现了,时间复杂度O(n)。
二叉树如何查找元素?从根节点向下遍历,就查找二叉树来说,时间复杂度是O(log n)。
但是二叉树有一个问题,如果根节点是到叶子节点如果是顺序插入的话,二叉树就会变成一个线性的链表。
鉴于二叉树的缺点,我们需要一种平衡二叉树来提高我们的查询效率。
但是平衡二叉树还是有一个问题,当树的节点足够多的情况下,树的高度还是会很高,定值查询依然会有瓶颈。
B-树结构
B树为了保证树的高度不要太高于是对树的每个节点进行了横向的扩展,也即是每一个节点可以可以存放多个数据,那么这样来说,树的高度就可以降低了。这种横向扩展的结构我们称做为页,虽然B树解决了树的高度问题,但是同时带来一个问题,那就是每个页里面都有存放数据,io操作时依然会带来很大的性能开销。
B+树结构
B+树像较与B树有两个改变
- 将数据只存在在叶子节点上
- 叶子节点上增加一个横向指针
数据存在叶子节点的好处?
根节点和中间节点就能存储更多的数据,mysql默认的页大小是16kb,如果根节点和中间节点不存放数据的话,就能存放更多的索引数据,就能减少磁盘的IO,比如上述结构的,11我们只需两次io就能真正的查询到数据。
叶子节点的横向指针的好处?
叶子节点的横向指针可以支持范围查询,像我们hash索引就不能支持范围查询。
聚簇索引和非聚簇索引
叶子节点的data存放了实际数据的就是聚簇索引,innerDB就是聚簇索引的实现,叶子节点的data只存放了数据的磁盘地址的就是非聚簇索引,myisam就是非聚簇索引的实现,想要真正定位到数据还要一次IO操作。
为什么innerDb希望我们建一个整形自增的主键索引?
整形的好处大概有两个,一个是方便比较,第二个是相对占用的空间小,自增的目的是为了减少树的旋转。
关于设计表的几个建议
- 建议使用innerDb引擎,支持事务、表锁、行锁、聚簇索引
- 最好有整形自增主键,强调一点根据数据量选用int或者bigint,尽量避免主键到头的尴尬
- 索引最好有唯一索引和复合索引搭配使用,不要滥建索引,会降低写的性能,树的旋转耗时
- 列字段占用空间越小越好,可以使用枚举来代替字符串
- 最好有create_time 和 update_time字段,方便定位问题
- 最好预留几个字段,方便扩展
- 字段备注越详细越好,方便后来者熟悉业务
- 数据表最好一次建好,后续执行DML会耗时,表越大越耗时,修改过程中会拒绝写操作
- 表字段不宜太多,可以垂直拆分成多个表