前言
学习自用,有错麻烦提一下
整体
首先MySQL的整体结构分为两层,server层和引擎层,可见上图,server层包含跨存储引擎的功能,如存储过程、触发器、视图,函数,也就是所有存储引擎都可以用到,或者说和存储引擎无关的功能,还有一个通用的日志模块 binglog日志模块。而引擎层,即MySQL的引擎,如InnoDB,MyISAM等,略
SQL语句执行顺序与整体结构关系
- 一开始是用户会通过连接器连接,连接器作用是认证用户并创建连接,我们常见的mysql -u root -p 密码即是这一步的;在项目中一般我们会创建一个连接池以防止频繁创建销毁的开销,(参考资料1提到长连接使用太久会内存上涨?参考资料10也提到了,还有解决办法)
- 连接后会先查询缓冲,是否执行过当前语句,以key-value的方式存储,应该是语句->结果的存储,这个查询缓存在MySQL8.0版本后被去掉了,原因是对于不同表的查询,或者是经常更新的表,缓存的刷新比较快,缓存经常会没用
- 如果上面的缓冲没命中,则进行下一步的分析器,也就是一个语法词法分析,可以参考编译原理,词法分析识别关键字,语法分析判断语法正确性,并随后生成一个解析树(语法树,其他编程语言编译也是这步骤)
- 分析完后,是优化器的阶段,这里也是个大头,一条查询可以有多种执行方法,最后都是返回相同结果。优化器的作用就是找到这其中最好的执行计划会优化语句的执行,其他的一大部分是索引选择的优化,这个太复杂了..,(更详细TODO),
- 最后是一个执行器的阶段,会与数据库引擎层交互,存储引擎会暴露一些API给执行器,
细节
分析器
对于一个查询语句同时出现了from.where,group by,having,order by的时候,顺序见上面
如果是 select from 学生表,成绩表 where 成绩>60 group by 啥 having
- 首先要把from后的表内数据做一个笛卡尔积读入内存(是buffer pool吗),可以称之为虚表,
- 接着对虚表内数据进行一个where筛选(不读的同时筛选?),
- 接着把虚表内数据进行group by划分
- 再对结果进行一个having划分
- 最后再是select目标列
优化器
先给个例子: 上面所说的一种语句有多种运行方式
select * from tb_student A where A.age='18' and A.name='张三';
a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是18。
b.先找出学生中年龄18岁的学生,然后再查询姓名为“张三”的学生。
MySQL使用基于成本的查询优化器(Cost-Based Optimizer,CBO)。它会尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最少的一个。 优化器会根据优化规则对关系表达式进行转换,这里的转换是说一个关系表达式经过优化规则后会生成另外一个关系表达式,同时原有表达式也会保留,经过一系列转换后会生成多个执行计划,然后CBO会根据统计信息和代价模型(Cost Model)计算每个执行计划的Cost,从中挑选Cost最小的执行计划。由上可知,CBO中有两个依赖:统计信息和代价模型。统计信息的准确与否、代价模型的合理与否都会影响CBO选择最优计划。(是什么来的 )
关于权限检查
这个好像有点争议,可以看参考资料5,因为不确定暂时把这方面的东西都删去了
此篇有提到它的观点
参考资料
- 图来源https://zhuanlan.zhihu.com/p/61546435
- https://zhuanlan.zhihu.com/p/48048479
- https://zhuanlan.zhihu.com/p/126722329mysql整体
- https://zhuanlan.zhihu.com/p/95082274这里讲到权限查询的争议
- https://zhuanlan.zhihu.com/p/86906096查询语句顺序,这篇好像不太靠谱
- https://zhuanlan.zhihu.com/p/48048479查询语句顺序,where join,having
- 优化器查询的例子
- 讲了连接器长连接的问题
TODO
- 更多啊,各种buffer,怎么往下到磁盘,,现在没时间弄了2020年8月25日