摘要
本文站在后端开发的角度,讲述一条SQL从客户端发送到MySQL服务器进行处理,并将结果返回给客户端的过程。这个过程中涉及的操作会在后面的文章中做详细的分析。
连接建立
我们通常使用ORM框架来生成SQL语句,在发送SQL语句给MySQL服务器之前,需要与其建立连接。MySQL驱动帮助我们建立起后端服务与MySQL的连接,通过这个连接就可以发送SQL和接收MySQL返回的结果。
后端服务可以开启多个线程并发访问MySQL,每个线程都需要与MySQL建立连接。后端服务与MySQL使用TCP/IP协议建立连接,连接的建立和销毁开销较大。为了避免频繁建立和销毁连接,引入池化的思想,后端服务会使用MySQL连接池,用完的连接不立即销毁,而是放在连接池中方便下次使用。常用的MySQL连接池有Druid、C3P0、DBCP、HikariCP等。类似地,MySQL也有一个连接池。建立连接关系的过程如下图所示,
MySQL维护了一个线程池,为每个活跃的连接分配一个线程,来执行SQL语句和返回结果。
解析与优化
查询缓存
如果客户端发送过来多条相同的SQL,那么可以直接从缓存中获取查询结果,提高MySQL的性能。只不过在5.7.20
版本开始,MySQL就不再建议使用缓存,因为缓存维护的成本较高,而提升的性能优先。在8.0
版本中,MySQL直接删除了缓存。
语法解析
对SQL进行文本分析,校验语法规则,将SQL中涉及的字段、表和查询条件提取出来存放到MySQL内部使用的数据结构中。
查询优化
一条SQL一般对应多种执行计划(可以通过EXPLAIN关键字查询执行计划),每个执行计划的执行成本不同,MySQL会选择执行成本最小的执行计划。执行成本主要包含两个部分:
- IO成本:MySQL将数据从磁盘读取到内存的数据量。注意MySQL从磁盘读取数据以页为单位,一页包含多条记录,每次读取会把满足条件的页和相邻的页都读取到内存。
- CPU成本:将查询到内存的记录逐行判断是否满足查询条件,记录行数影响CPU成本。
IO成本和CPU成本的和就是对应的执行计划的成本。
存储引擎
查询优化器会调用存储引擎执行SQL,也就是说SQL实际上是在存储引擎中执行的。