MySQL系列文章
磁盘存储数据原理
- 数据持久化通常是指存储在硬盘里,硬盘是由很多的盘片组成,为什么叫磁盘就是因为通过盘片表面的磁性物质来存储数据。计算机中所有的数据传输归根结底都是二进制,把盘片放在显微镜下放大,可以看到盘片表面是凹凸不平的,凸起的地方被磁化,代表数字 1,凹的地方没有被磁化,代表数字 0,因此磁盘本质上还是通过硬件磁化突起来存储二进制数据。
- 硬盘是都是由盘片、磁头、盘片主轴、控制电机、磁头控制器、数据转换器、接口、缓存等几个部分组成。所有的盘片都固定主轴上。所有的盘片之间是绝对平行的,在每个盘片的盘面上都有一个磁头。数据读取的过程本质上就是磁头在盘片旋转中识别二进制数据的过程
- 硬件及操作系统往往将主存和磁盘存储分割为连续的大小相等的块。每个存储块称为一页(在许多操作系统中,页的大小通常为 4k),主存和磁盘以页为单位交换数据,从磁盘读取数据时并不是要多少读多少,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存
MySQL的存储结构
- 表空间table space->段segment->区extends->页page
- 页的概念
- 页是InnoDB中数据管理的最小单位。当我们查询数据时,其是以页为单位,将磁盘中的数据加载到缓冲池中的。同理,更新数据也是以页为单位,将我们对数据的修改刷回磁盘。
- 每个数据页16kb,一个数据页大约16k,也就是说一个数据区可以包含64个连续的数据页。
- page头部保存了两个指针,分别指向前一个Page和后一个Page,头部还有Page的类型信息和用来唯一标识Page的编号。根据这个指针分布可以想象到Page链接起来就是一个双向链表
聚簇索引与非聚簇索引
- 聚簇索引
- 聚簇索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据。这个特性决定了索引组织表中数据也是索引的一部分,每张表只能拥有一个聚簇索引。
- 优点:数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快,聚簇索引对于主键的排序查找和范围查找速度非常快
- 缺点:
- 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
- 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。
- 二级索引(手动添加的索引)访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
- 非聚簇索引
- 在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找。
- 辅助索引叶子节点存储的不再是行的物理位置,而是主键值。
- 通过辅助索引首先找到的是主键值,再通过主键值去主键索引树中找到对应的数据行。
页分裂
- 首先页分裂的主要目的是为了保证两个连续的数据页内的主键值保证顺序
- 两个数据页之间会有指针相连,前一个数据页指后一页,后一个数据页指向前一页。形成双向链表。
- 之所以建表建议用自增Id做主键其中之一的原因就是,自增字段会避免页分裂。
- 主键字段保证连续递增可以保证每个数据页之间的主键有序性,后面数据页中的数据行的主键值需要大于前一个数据页中数据行的主键值,查找数据时可以直接用二分查找快速定位到主键行位置。
- 如果自定义主键的话会导致数据页中的主键值大小不能满足有序二分查找的使用的条件,此时就会通过数据移动的方式产生页分裂满足数据页之间的数据有序。