重新整理 mysql 基础篇————— 索引模型[五]
前言
简单整理一下索引模型。
正文
对我们开发人员来说,索引感觉非常的重要。
因为索引好用,但是不能多建,因为这影响插入,不能少建,因为这影响读取。
有些为了能够多建索引,通过从多个从库中读取数据,再重新整合数据来建立新的数据结构,建立新的索引。
hash 表
在索引模型中hash表非常常见,这里值的是应用内存中的索引模型,而不是数据库中的索引模型。
因为现在数据库越来越大,比较容易发生hash碰撞,形成链表,故而innodb不是用的hash这种方式。
hash索引是如何实现的在细节篇将会介绍。
hash索引可以想象成hashtable 一样,通过key-value的形式来组织结构。
同样因为是key-value 这种模式,那么出现问题的情况也很明显了。
就是key-value这种形式只能适合等值查询,不适合范围查询。
哈希表这种结构适用于只有等值查询的场景,有序数组在等值查询和范围查询场景中的性能就都非常优秀。
有序数组
有序数组不用过多的介绍吧,我们经常写的数组就是有序数组。
有序数组这种结构的索引查询效率是最高的,有序数组不仅适合等值查询同样适合范围查询的原因,在于它本来就是排好序的。
如果利用一些简单的算法,比如二分法,那么查询效率可想而知。
但是最美好的东西,往往最不适用,因为这种美好的情况,是在于只读,而不更新的角度上来讲的。
比如1到10000直接要插入一个5,那么5后面的都必须后移来给我留给位置。
有序数组索引只适用于静态存储引擎。
平衡二叉树
这种算法结构网上满大街介绍。
这里介绍一个二叉树的缺点,那就是太小,路太长。
二叉树特点就是只有一个节点只有两个节点,那么如果是100w条数据,那么就有一个比较大的问题,那么就是树太高了。
树太高有一个缺点,那就是大部分数据在叶子节点,而上面的很多判断都是低收益的判断。
还有一个缺点,那就是存储缺点,一个二叉树如何存取呢?那么可能就是每一层存储到一个数据块中,那么访问一个20层的二叉树,访问一条数据,大概率需要读取20次磁盘出来,因为数据大多数在叶子节点。
既然二叉树不行,因为太高了,能不能降低呢?可以的,可以使用n叉树来解决这个问题。
n叉树
以InnoDB的一个整数字段索引为例,这个N差不多是1200。这棵树高是4的时候,就可以存1200的3次方个值,这已经17亿了。
考虑到树根的数据块总是在内存中的,一个10亿行的表上一个整数字段的索引,查找一个值最多只需要访问3次磁盘。
其实,树的第二层也有很大概率在内存中,那么访问磁盘的平均次数就更少了。
聚簇索引和非聚簇索引的区别
主键索引也被称为聚簇索引,非主键索引也被称为二级索引。
聚簇索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,也将聚集索引的叶子节点称为数据页。
一般建表会用一个自增主键做聚簇索引,没有的话MySQL会默认创建,但是这个主键如果更改代价较高,故建表时要考虑自增ID不能频繁update这点。
我们日常工作中,根据实际情况自行添加的索引都是辅助索引,辅助索引就是一个为了需找主键索引的二级索引,现在找到主键索引再通过主键索引找数据;
Innodb通过主键聚集数据,如果没有定义主键,innodb会选择非空的唯一索引代替。如果没有这样的索引,innodb会隐式的定义一个主键来作为聚簇索引。
聚簇索引的优缺点
优点:
1.数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
2.聚簇索引对于主键的排序查找和范围查找速度非常快
缺点:
1.插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
2.更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。
3.二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找。辅助索引叶子节点存储的不再是行的物理位置,而是主键值。通过辅助索引首先找到的是主键值,再通过主键值找到数据行的数据页,再通过数据页中的Page Directory找到数据行。
Innodb辅助索引的叶子节点并不包含行记录的全部数据,叶子节点除了包含键值外,还包含了相应行数据的聚簇索引键。
辅助索引的存在不影响数据在聚簇索引中的组织,所以一张表可以有多个辅助索引。在innodb中有时也称辅助索引为二级索引。
结
以上只是个人整理,如有错误,望请指点。下一节,锁。