SQL语句是如何执行的?(MySQL篇)
MySQL体系架构
MySQL是典型的C/S架构数据库管理系统,数据库服务器和客户端分别运行在服务器和终端计算机上,通过网络进行通信和数据交换。默认情况下,MySQL服务通过3306端口开放。
类似采用C/S架构的数据库系统还包括:
-
Oracle
-
PostgreSQL
-
MongoDB
-
SQL Server
MySQL服务器端使用mysqld程序,其职责范围可总结为三个方面:连接层、SQL层、存储层。其中连接层主要是负责与客户端建立连接,接收来自客户端的SQL;SQL层负责对SQL语句进行处理;存储层负责数据的读取和存储。
MySQL SQL处理层
SQL处理层包括缓存查询、解析器、优化器、执行器等 。
- 解析器
解析器负责验证和 解析传入的命令 ,包括语法和语义上的分析。如果语法不正确或语义不合理,则直接报错,若符合语法且语义合理则将命令(解析出的中间结果,如SQL语法分析树)交由优化器进行优化。
-
优化器
优化器负责把关系表达式转换为查询执行计划。常用优化策略:无用条件去除。
-
执行器
执行器负责对查询执行计划进行执行,涉及与存储引擎的交互。执行器模块拆解开包括表维护模块(Table Maintainence)、表修改模块(TableModification)、状态报告模块(StatusReport)等等。
MySQL存储引擎
InnoDB
MyISAM
NDA Cluster
Memory
SQL执行原理
如何分SQL性能:以MySQL为例
从数据库优化层面,了解现有SQL语句性能是优化的重要基础,MySQL提供了profiling参数进行SQL剖析。至少截止到MySQL8.0.32(我目前使用过的最新版本MySQL),还可以通过以下语句查询剖析模式是否开启:
select @@profiling;
通过以下语句设定开启剖析模式(若profiling为0则是关闭剖析模式):
set profiling=1
开启剖析模式之后,当你执行了一条SQL语句,就可以通过show profile语句查询(最近一条)语句的性能剖析数据:
profiling之后: 基于performance schema进行性能剖析
需要注意,当你执行show profile或select @@profiling语句,会收到DBMS的友情提示:@@profiling和show profile已被废弃,在未来的MySQL发行版中将被移除。
'@@profiling' is deprecated and will be removed in a future release.
'SHOW PROFILE' is deprecated and will be removed in a future release. Please use Performance Schema instead
替代的性能剖析方案是通过performance schema来达成通用的目的,详情可参考MySQL :: MySQL 8.0 Reference Manual :: 27.19.1 Query Profiling Using Performance Schema。
按照官方文档的介绍,性能剖析主要涉及几个表:setup_actors表、
-
setup_actors表可用于限制主机、用户或帐户对历史事件的收集,以减少运行时开销和在历史表中收集的数据量。以下例子展示了如何限制特定用户收集SQL历史事件。 先查询用户对历史事件的收集权限
SELECT * FROM performance_schema.setup_actors;
为了禁止所有前台操作都被监控和记录,需要通过如下语句进行限制。
UPDATE performance_schema.setup_actors SET ENABLED = 'NO', HISTORY = 'NO' WHERE HOST = '%' AND USER = '%';
为了使特定用户具备历史事件收集、监控的权限,通过如下语句为用户开放权限:
INSERT INTO performance_schema.setup_actors (HOST,USER,ROLE,ENABLED,HISTORY) VALUES('localhost','YOUR_USER','%','UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE '%stage/%'; YES','YES');
-
setup_instruments表列出了可以收集的事件类。通过更新setup_instruments表,确保启用语句和阶段检测。有些工具可能已经默认启用。
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE '%statement/%';
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE '%stage/%';
-
确保启用events_statements_*和events_stages_*消费者。一些消费者可能在默认情况下已经启用。
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%events_statements_%';
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME LIKE '%events_stages_%';
完成上述配置后,就可以使用performance schema进行SQL性能剖析了。 执行需要剖析的SQL语句,如:
select FK_TASK_ID as T, count(*) as count from t_image ti group by ti.FK_TASK_ID ;
通过查询events_statements_history_long表来确定语句的EVENT_ID。这一步类似于运行SHOW PROFILES来识别Query_ID。下面的查询产生的输出类似于SHOW PROFILES:
通过查询events_stages_history_long表以检索语句的阶段事件,得到语句的性能剖析报告
mysql> SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT
FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%FK_TASK_ID%';
一条SQL语句背后的操作
从events_stages_history_long表中检索出的事件反映了一条SQL语句背后需要执行多少操作(不同版本的MySQL操作会有所不同)。MySQL8.0.32版本下,操作包含:
-
starting
-
executing hook on transaction begin
-
staring
-
checking permission
-
opening tables
-
init
-
system lock
-
optimizing
-
statistics
-
preparing
-
executing
-
end
-
query end
-
waiting for handler commit
-
closing tables
-
freeing items
-
cleaning up
参考文档
- MySQL :: MySQL 8.0 Reference Manual :: 16.11 Overview of MySQL Storage Engine Architecture
- 03丨学会用数据库的方式思考SQL是如何执行的-极客时间
- Performance Schema Quick Start
- SQL解析在美团的应用 - 美团技术团队
- Understanding MySQL Internals