mysql整体架构:client层——>server层——>存储引擎
- client向server层发送SQL语句,server层通过连接器接收
- server层的分析器对SQL语句进行语法分析,转变为AST抽象语法树
- server层使用优化器对语句中具体查询的数据
- RBO:基于规则的优化
- CBO:基于成本优化
- 执行器与存储引擎进行IO交互,获取查询结果
数据存储在磁盘,一般情况况下查询速率慢,都是卡在IO上。因此需要在满足需求的前提下提高IO效率:
-
减少IO次数
-
减少IO量
一些概念
-
局部性原理:数据和程序都有聚集成群的倾向,同事之前访问过的数据很可能再次查询。
-
磁盘预读:内存跟磁盘在发生数据交互的时候,一般情况下有一个最小的逻辑单元,即"页"/"datapage",页一般由操作系统决定是多大,一般是4k或8k。而进行数据交互的时候,可以取页的整数倍来读取。如innodb引擎每次读取数据都是16k
-
OLAP与OLTP
-
OLAP:联机分析处理:对海量历史数据进行分析,产生决策性的影响(数据仓库——Hive等)
-
OLTP:联机事务处理:要求在很短的时效内返回对应的结果(数据库——关系型数据库)
-
B+树
-
每个关键字对应一棵子树
-
每个结点关键字个数n的范围是[m/2]<=n<=m
-
叶节点是包含信息的,其他所有非叶节点仅起到索引作用,包含了对应子树的最大关键字和指向该子树的指针
存储本身是存储在磁盘的,查询数据时优先将索引加载在内存。索引存储的信息是这种key-value类型的数据:
-
key:唯一标识,也就是实际数据行中存储的值
-
文件地址(offset):偏移量
-
Mysql索引系统的数据结构采用3~4层的B+树,这个层数是由具体磁盘计算出来的。3~4层的B+树就可以存放千万级的数据,如果还需存放则需要扩容加表。
-
B+树的最底层即叶子节点是所有的数据,它形成了一个双向链表,用于对主键的范围查找和分页查找。因此B+树有两种查找运算,还有一种就是正常的从根节点随机查找
-
在一个磁盘块中,指针大小是固定的,因此当选择某字段当索引时,应该尽量减小键值所占用的空间,这样可以指数级地增加用于存放数据的空间
当索引使用不同数据结构:
-
hash:哈希冲突;范围查询时需逐个遍历;对于内存空间要求高。mysql中也存在hash,即memory引擎使用的是hash索引,innodb支持自适应hash,即系统根据数据类型判断使用哪种存储结构
-
树
-
二叉树:无序
-
BST:二叉查找树:插入时有序,左子树小于子树根节点,右子树大于子树根节点
-
插入连续值时,可能退化成链表,时间复杂度提高
-
AVL:平衡二叉查找树:有序,为了解决连续值退化的问题,通过左旋或右旋让树平衡,保持最短子树和最长子树高度不能超过1
-
通过插入性能的损失来弥补查询性能的提升
-
红黑树:在旋转平衡的基础上,添加变色的行为。保持最长子树不超过最短子树的2倍即可。使得查询性能和插入性能近似一致
-
随着数据的插入,树的深度越来越深,意味着IO次数越多,影响数据读取的效率,因此使用开始使用树
-
B树:多岔树,有序,非叶子节点也是存储着数据的,占用空间较大
-
B+树:多岔树,有序,只有叶子节点存储着数据,非叶子节点存储的是指针
索引的创建跟存储引擎是挂钩的,存储引擎表示不同数据在磁盘的不同组织形式
在windows上的Mysql中,文件都是以不同后缀并成对的形式存在。数据结构用的都是B+树,而存储形式又有所不同
-
.frm:存放表结构
-
.MYD和.MYI:引擎是myisam,非聚簇索引。
-
.MYD:数据,Data
-
.MYI:索引,index
-
.ibd:存储数据+索引,即引擎是innodb。只能有一个聚簇索引,可以有很多非聚簇索引。在插入数据时,必须要包含一个索引的key值。这个索引的key值可以是主键;若没有主键也可以是唯一键;若唯一键也没有,就会有一个自生成的6字节的rowid(对用户不可见)
——聚簇索引与非聚簇索引——二者取决于数据和索引是否是放在一起的
——mysql表中有且至少有一个索引
一些概念2.0:
回表:假设表中有一个聚簇索引和一个非聚簇索引,当查询整行记录时,通过非聚簇索引查询到主键id(即聚簇索引),再根据id查询到整行的记录。这种现象叫做回表,回表走了2次B+树
-
定义:根据普通索引查询到聚簇索引的key值之后,再根据key值在聚簇索引中获取所有行记录
索引覆盖:若查询结果包含普通索引列和聚簇索引列,则会直接返回,不需要从聚簇索引查询任何数据,这就叫索引覆盖
-
注:面试常问——在设置主键时是否需要自增?答:在满足业务需求的情况下,能自增尽量自增。因为自增是累加的,对前面的数据没有影响,无需做插入操作,也就无需做磁盘块/页分裂的操作(当在一页数据里插入数据时,如果数据满了就需要分裂成多个页或者磁盘块来存储,父亲节点也可能需要分裂,而分裂会影响效率)。追加的效率较高
最左匹配:组合索引的匹配规则。若一张表里有两列是组合索引,那么使用时必须先匹配左侧的列,再匹配右侧列
-
select * fro table where name=? and age=? 允许使用
-
select * fro table where name=? 允许使用
-
select * fro table where age=? 无法使用
-
select * fro table where age=? and name=? 允许使用
-
只要查询条件是组合索引,那么就算顺序相反,mysql内部的优化器会调整对应的顺序
索引下推(mysql5.7后特性):使用组合索引时,直接根据组合索引在存储引擎中获取对应数据,无需在server层二次过滤(5.7之前),减少了server层于存储引擎的交互,减少了IO量,提高了效率
profiling——mysql自带的性能分析工具(单条语句)
-
开启profiling:set profiling=1;
-
执行SQL语句,然后show profiles; 即可查出上条语句执行的实际时间
-
想要查询profiles结果表中具体某条语句的所有状态耗费时长,或者想查询某条语句的某个状态的使用情况,根据可使用profiles表语句对应的Query_ID来查询,语法如下:show profile for [type] query [id]。但这种查询方式在未来版本可能会被其他工具所取代
进阶--Myysql性能模式:
5.7默认开启性能模式,在初始数据库中,会有一个performance_schema库,里面有众多相关表,而通过show variables like \'performance_schema\';查询性能模式的开启状态。而修改状态无法直接update,需要更改mysql配置文件my.cnf