首页 > 数据库 > MySQL > Java培训MySQL体系构架、存储引擎和索引结构
对某项技术进行系统性的学习,始终离不开对该项技术的整体认知。只有领略其全貌,方可将各块知识点更好的串联起来。为了进一步理解和学习MySQL,我们有必要了解一下MySQL的体系构架、存储引擎和索引结构。
MySQL体系构架
以下是官网MySQL体系构架图,我们稍微对其进行了层级划分。
英文不好的同学可以看下中文版的:
由上至下,我们可以MySQL的体系构架划分为:1.网络接入层 2.服务层 3.存储引擎层 4.文件系统层
网络接入层
提供了应用程序接入MySQL服务的接口。客户端与服务端建立连接,客户端发送SQL到服务端。
服务层
管理工具和服务
系统管理和控制工具,例如备份恢复、Mysql复制、集群等
连接池
主要负责连接管理、授权认证、安全等等。每个客户端连接都对应着服务器上的一个线程。服务器上维护了一个线程池,避免为每个连接都创建销毁一个线程。当客户端连接到MySQL服务器时,服务器对其进行认证。可以通过用户名与密码认证,也可以通过SSL证书进行认证。登录认证后, 【关注尚硅谷,轻松学IT】服务器还会验证客户端是否有执行某个查询的操作权限_ 。
由于每次建立连接需要消耗很多时间,连接池的作用就是将这些连接缓存下来,下次可以直接用已经建立好的连接,提升服务器性能。
SQL接口
接受用户的SQL命令,并且返回用户操作的结果。
查询解析器
SQL命令传递到解析器的时候会被解析器验证和解析。
MySQL是一个DBMS(数据库管理系统),没法直接理解SQL语句。Parser负责对SQL语句进行解析好让DBMS知道该怎么做。
查询优化器
SQL语句在查询之前会使用查询优化器对查询进行优化。它使用的是“选取-投影-联接”策略进行查询以此选择一个最优的查询路径。
select uid,name from user where gender = 1;
select 查询先根据 where 语句进行选取,而不是先将表全部查询出来以后再进行条件过滤
select查询先根据 uid 和 name 进行属性投影,而不是将属性全部取出以后再进行过滤
将这两个查询条件联接起来生成最终查询结果
缓存(8.0版本之前支持查询缓存,8.0之后不支持了)
查询缓存,如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。
通过LRU算法将数据的冷端溢出,未来得及时刷新到磁盘的数据页,叫脏页。
这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等
存储引擎层
负责数据的存储和读取,与数据库文件打交道。服务器中的查询执行引擎通过API与存储引擎进行通信,通过接口屏蔽了不同存储引擎之间的差异。
MySQL采用插件式的存储引擎。MySQL为我们提供了许多存储引擎,每种存储引擎有不同的特点。我们可以根据不同的业务特点,选择最适合的存储引擎。
MySQL区别于其他数据库的最重要的一个特点就是插件式的表存储引擎,注意:存储引擎是基于表的。
系统文件层
该层主要是将数据库的数据存储在文件系统之上,并完成与存储引擎的交互。
存储引擎是基于表的,以下分别使用MyISAM和InnoDB存储引擎建立两张表,看看其在文件系统中对应的文件存储格式。
存储引擎为MyISAM:
存储引擎为InnoDB:
除了.ibd文件InnoDB还有一种文件的存储格式为.ibdata文件,那么他们之间有什么区别呢?
InnoDB的数据存储方式能够通过配置来决定是使用共享表空间存放存储数据,还是用独享表空间存放存储数据。独享表空间存储方式使用.ibd文件,并且每个表为一个ibd文件。共享表空间存储方式采用.ibdata文件,所有的表共同使用一个ibdata文件,即所有的数据文件都存在一个文件中。决定使用哪种表的存储方式可以通过mysql的配置文件中innodb_file_per_table选项来指定。
InnoDB默认使用的是独享表的存储方式,这种方式的好处是当数据库产生大量文件碎片的时,整理磁盘碎片对线上运行环境的影响较小。
【拓展】一个SQL语句在MySQL中的整体流程
:
简化版:
存储引擎
了解存储引擎
MySQL中的数据用各种不同的技术存储在文件(或者内存)中。每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,能够获得额外的速度或者功能,从而改善应用的整体功能。这些不同的技术以及配套的相关功能在MySQL中被称作存储引擎(也称作表类型)。
MySQL区别于其他数据库的最重要的一个特点就是插件式的表存储引擎,也就是说存储引擎是基于表的。
存储引擎的概念是MySQL里面才有的, 【关注尚硅谷,轻松学IT】不是所有的关系型数据库都有存储引擎这个概念 。其它数据库系统 (包括大多数商业选择)仅支持一种类型的数据存储, 也就是说采用“ 一个尺码满足一切需求 ”的存储方式,也意味着“功能强大,性能平庸”。而MySQL默认配置了许多不同的存储引擎,你可以根据业务需求选取一种最适配最高效的存储引擎。这也是为什么MySQL为何如此受欢迎的主要原因之一。
存储引擎分类
查看当前安装的MySQL版本支持的存储引擎
-- 查看MySQL版本
select version();
-- 查看版本支持的存储引擎
show engines;
我本地安装的社区版MySQL,版本号为5.7.23,支持9种存储引擎或者说是8种(FEDERATED NO SUPPORT 不支持FEDERATED),而官网提供了10种存储引擎。本地与官网支持的存储引擎略微不同,个人估计是社区版和商用版的差别的缘故,或者是安装时候配置项设置导致的差异,有清楚的小伙伴还望告知一下。
官网5.7版本支持的10种存储引擎:
常用存储引擎特性
存储特性要求
存储引擎常见的目标特性要求
并发性:某些应用程序比其他应用程序具有更高的颗粒级锁定要求(如行级锁定)。
事务支持:并非所有的应用程序都需要事务,但对的确需要事务的应用程序来说,有着定义良好的需求,如ACID兼容等。
引用完整性:通过DDL定义的外键,服务器需要强制保持关联数据库的引用完整性。
物理存储:它包括各种各样的事项,从表和索引的总的页大小,到存储数据所需的格式,到物理磁盘。
索引支持:不同的应用程序倾向于采用不同的索引策略,每种存储引擎通常有自己的编制索引方法,但某些索引方法(如B-tree索引)对几乎所有的存储引擎来说是共同的。
内存高速缓冲:与其他应用程序相比,不同的应用程序对某些内存高速缓冲策略的响应更好,因此,尽管某些内存高速缓冲对所有存储引擎来说是共同的(如用于用户连接的高速缓冲,MySQL的高速查询高速缓冲等),其他高速缓冲策略仅当使用特殊的存储引擎时才唯一定义。
性能帮助:包括针对并行操作的多I/O线程,线程并发性,数据库检查点,成批插入处理等。
其他目标特性:可能包括对地理空间操作的支持,对特定数据处理操作的安全限制等。
以上特性很多是互斥的,一个存储引擎只能具备其中某些要求。
具体查考官网Storage Engines Feature Summary
Notes:
下文主要介绍InnoDB MyISAM Memory三种存储引擎,以下是三者简要特性对比
InnoDB引擎
InnoDB 是一个事务安全的存储引擎,它具备提交、回滚以及崩溃恢复的功能以保护用户数据。InnoDB 的行级别锁定保证数据一致性提升了它的多用户并发数以及性能。InnoDB 将用户数据存储在聚集索引中以减少基于主键的普通查询所带来的 I/O 开销。为了保证数据的完整性,InnoDB 还支持外键约束。默认使用B+TREE数据结构存储索引。
特点
业务场景
InnoDB引擎调优
补充:事务(ACID)
A 事务的原子性(Atomicity):指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成.
.
C 事务的一致性(Consistency):指事务的运行并不改变数据库中数据的一致性.例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变.
.
I 独立性(Isolation):事务的独立性也有称作隔离性,是指两个以上的事务不会出现交错执行的状态.因为这样可能会导致数据不一致.
.
D 持久性(Durability):事务的持久性是指事务执行成功以后,该事务所对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚.
MyISAM引擎
MyISAM既不支持事务、也不支持外键、其优势是访问速度快,但是表级别的锁定限制了它在读写负载方面的性能,因此它经常应用于只读或者以读为主的数据场景。默认使用B+TREE数据结构存储索引。
特点
业务场景
MyISAM引擎调优
Memory引擎
在内存中创建表。每个MEMORY表只实际对应一个磁盘文件(frm 表结构文件)。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。要记住,在用完表格之后就删除表格,不然一直占据内存空间。
特点
业务场景
存储引擎构架
为了进一步深入理解MySQL存储引擎,我们有必要了解一下存储引擎的数据存储结构,在此之前,我们得先了解下数据在文件系统中的存储。
磁盘基本知识
数据库的数据存储在文件系统中。文件系统是操作系统用来 明确 存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件 的方法和数据结构。磁盘上数据必须用一个三维地址唯一标示:柱面号、盘面号、块号(磁道上的盘块)。
硬盘只是磁盘的一种,或说是经典代表,以下通过硬盘模型图讲解磁盘中的各个概念。
硬盘整体模型图
硬盘模型图
磁盘重点概念
物理扇区(physical sector)与逻辑扇区(logical sector)
近年来,为了最求更高的硬盘容量,便出现了扇区存储容量为2048、4096等字节的硬盘,我们称这样的扇区为”物理扇区”。这样的大扇区会导致许多兼容性问题,有的系统或软件无法适应。为了解决这个问题,硬盘内部将物理扇区在逻辑上划分为多个扇区片段并将其作为普通的扇区(一般为512字节大小)报告给操作系统及应用软件。这样的扇区片段我们称之为“逻辑扇区”。实际读写时由硬盘内的程序(固件)负责在逻辑扇区与物理扇区之间进行转换,上层程序“感觉”不到物理扇区的存在。
逻辑扇区是硬盘可以接受读写指令的最小操作单元, 【关注尚硅谷,轻松学IT】是操作系统及应用程序可以访问的扇区,多数情况下其大小为512字节。我们通常所说的扇区一般就是指的逻辑扇区。物理扇区是硬盘底层硬件意义上的扇区,是实际执行读写操作的最小单元。是只能由硬盘直接访问的扇区,操作系统及应用程序一般无法直接访问物理扇区。当要读写某个逻辑扇区时,硬盘底层在实际操作时都会读写逻辑扇区所在的整个物理扇区。
磁盘容量计算
块(Block)/簇(Cluster)
块/簇两者指的是同一个逻辑上的概念,只是在Linux与Windows中的称呼不同。
块/簇 用来干什么的
磁盘的最小单位是扇区,操作系统使用的是 块/簇 作为IO的基本单位。
扇区是对硬盘而言,块是对文件系统而言,出于不同的需要。
查看块/簇的大小
不同文件系统中block的大小不一样。
Windows:(使用管理员命令提示行)
fsutil fsinfo ntfsinfo E:
Linux:
stat /home | grep "IO Block"
如下所示,Windows下E盘的Cluster的大小为4Kb大小,如下所示:
页(Page)
操作系统经常与内存和硬盘这两种存储设备进行通信,类似于“块”的概念,都需要一种虚拟的基本单位。与内存操作,是虚拟一个页的概念来作为最小单位。与硬盘打交道,就是以块为最小单位。
扇区、块/簇、页的关系
MySQL的InnoDB数据存储结构
MySQL的InnoDB数据存储结构可以划分为逻辑存储结构和物理存储结构。
前置:数据库磁盘读取与系统磁盘读取
物理存储结构
从物理意义上来看,InnoDB表由共享表空间、日志文件组(更准确地说,应该是Redo文件组)、表结构定义文件组成。若将innodb_file_per_table设置为on,则每个表将独立地产生一个表空间文件,以ibd结尾,数据、索引、表的内部数据字典信息都将保存在这个单独的表空间文件中。表结构定义文件以frm结尾,这个是与存储引擎无关的,任何存储引擎的表结构定义文件都一样,为.frm文件。
逻辑存储结构
InnoDB存储引擎的逻辑存储结构和Oracle大致相同,所有数据都被逻辑地存放在一个空间中,我们称之为表空间。表空间又由段、区、页组成。1 extent = 64 pages,InnoDB存储引擎的逻辑存储结构大致如图所示。
表空间(tablespace)
表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都是存放在表空间中。默认情况下InnoDB存储引擎有一个共享表空间ibdata1,即所有数据都放在这个表空间内。如果我们启用了参数innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内。关注终端研发部获取2T的面试java开发资料
对于启用了innodb_file_per_table的参数选项, 【关注尚硅谷,轻松学IT】需要注意的是,每张表的表空间内存放的只是数据、索引和插入缓冲,其他类的数据,如撤销(Undo)信息、系统事务信息、二次写缓冲(double write buffer)等还是存放在原来的共享表空间内。这也就说明了另一个问题:即使在启用了参数innodb_file_per_table之后,共享表空间还是会不断地增加其大小。
段(segment)
表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。
InnoDB存储引擎表是由索引组织的(index organized),因此数据即索引,索引即数据。InnoDB采取B+树作为存储数据的结构,数据段即为B+树的叶节点(上图的leaf node segment),索引段即为B+树的非叶子节点(上图的non-leaf node segment)。
InnoDB存储引擎对于段的管理是由引擎本身完成。
区(extent)
一个区是由64个连续的页组成的,每个页大小为16KB,即每个区的大小为1MB。对于大的数据段,InnoDB存储引擎最多每次可以申请4个区,以此来保证数据的顺序性能。
在我们启用了参数innodb_file_per_talbe后,创建的表默认大小是96KB,新建的InnoDB表就是一个区。区是64个连续的页,那创建的表的大小至少是1MB才对啊?其实这是因为在每个段开始时,先有32个页大小的碎片页(fragment page)来存放数据,当这些页使用完之后才是64个连续页的申请。
create table innodb_table(
id int primary key
)engine=innodb default charset=utf8;
页(page)
每个页大小为16KB,页是InnoDB磁盘管理的最小单位,整页整页的读取。
InnoDB中主要的页类型:
由页组成的链表,页之间是双向列表,页里面的数据是单向链表,这种结构组成了主键索引B+树,组成了叶子节点数据。
拓展:定位一条表记录的过程
select * from user where id = 29
这里id是主键,我们通过这棵B+树来查找,首先找到根页,你怎么知道user表的根页在哪呢?
其实每张表的根页位置在表空间文件中是固定的。系统经过解析sql语句,首先从找到user表的跟页面(一个表通常需要多个页面组成,跟页面就是起始页),层级遍历非叶子节点页(索引)读取到key值为29的指针(遍历非叶子节点的过程随着节点的遍历会将一个或多个页加载到内存), 【关注尚硅谷,轻松学IT】最后到指针指向的叶子节点所在的页中,然后遍历找出该条记录。
如果使用了二级索引则先读取二级索引page遍历这个二级索引,找到装有主键信息叶子节点page页,遍历找到该主键。然后再根据主键索引寻找到该条记录,关注终端研发部获取2T的面试java开发资料
索引结构
常见的索引结构
Mysql数据库中的常见索引结构有多种,常用Hash,B-树,B+树等数据结构来进行数据存储。树的深度加深一层,意味着多一次查询,对于数据库磁盘而言,就是多一次IO操作,导致查询效率低下。
前置:二叉搜索树
了解下二叉搜索树有助于我们理解B-树、B+树,二叉搜索树的特点是:
以下都是二叉搜索树:
如果要找到65,左边的二叉树需要扫描3层(3次IO),而右边的却需要6层。
B-Tree(B树)
B-tree树即B树,B即Balanced,平衡的意思。因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译,很容易让人产生误解。事实上,B-tree就是指的B树。
B树是一种多路搜索树,一棵m阶的B树满足下列条件:
以下是3阶B树
磁盘读取数据是以盘块(block)为基本单位的。
以下结合磁盘块作图
B树的特征:
B树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复,直到所对应的儿子指针为空,或已经是叶子结点;更多阅读:在100G内存下,MySQL查询200G大表会OOM么?
B+ Tree
B+树是B-树的变体,也是一种多路搜索树:(❀ 表示两者间的不同点)
B+树的特征:
B+树的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树可以在非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;
为什么B+ 树比B 树更适合作为索引?
Hash
哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。Memory存储引擎使用Hash。
Hash索引仅仅能满足”=”,“IN”和”<=>”查询,不能使用范围查询。也不支持任何范围查询,例如WHERE price > 100。
由于Hash索引比较的是进行Hash运算之后的Hash值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样。更多阅读:在100G内存下,MySQL查询200G大表会OOM么?
从上面的图来看,B+树索引和哈希索引的明显区别是:
InnoDB B+Tree结构来存储索引
。一个表中只能存在一个聚簇索引(主键索引),但可以存在多个非聚簇索引。
B+树 叶子节点包含数据表中行记录就是聚簇索引(索引和数据是一块的)。
B+树 叶子节点没包含数据表中行记录就是非聚簇索引(索引和数据是分开的)。
B+ 树可以存储多少行数据
InnoDB存储引擎也有自己的最小储存单元——页(Page),一个页的大小默认是16K。
mysql> show variables like 'innodb_page_size';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
磁盘扇区、文件系统、InnoDB存储引擎都有各自的最小存储单元
数据表中的数据都是存储在页中的,所以一个页中能存储多少行数据呢?假设一行数据的大小是1k,那么一个页可以存放16行这样的数据。更多阅读:在100G内存下,MySQL查询200G大表会OOM么?
如果数据库只按这样的方式存储,那么如何查找数据就成为一个问题?
因为我们不知道要查找的数据存在哪个页中,也不可能把所有的页遍历一遍,那样太慢了。
于是人们想到了用B+ 树的方式组织这些数据,下图以InnoDB为例。
pointer往往是6个字节,指明对应key值的页面位置信息。key一般为索引主键,如果为单字段 bigint 类型,则为8字节。如此可计算一个页大概可以存放16 * 1024/(6+8)=1170行数据。假设一行数据1k,那么2层B+ 树(第一层索引,第二层叶子节点 存数据)就可以存储1170 * 16 = 18 720行;三层则可以存储1170 * 1170 * 16=21902400行。
MyISAM B+Tree结构来存储索引
![](
MyISAM也使用B+Tree数据结构存储索引,但都是非聚簇索引。
以下是MyISAM主键索引存储图
可见,索引和数据是分开的 索引的data部分只是索引的地址值。其实上文也提到过,.MYI就是MyISAM表的索引文件,MYD是MyISAM表的数据文件。
文章转载来源于终端研发部
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70010293/viewspace-2889142/ ,如需转载,请注明出处,否则将追究法律责任。