이 기사에서는 MySQL의 SQL 실행 프로세스를 이해하고 MySQL이 쿼리 문을 어떻게 실행하는지 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다!
개발 엔지니어에게는 MySQL이 쿼리문을 어떻게 실행하는지 이해하는 것이 매우 필요하다고 생각합니다. [관련 추천 : mysql 동영상 튜토리얼]
먼저 MYSQL의 아키텍처가 어떤 모습인지 이해해야 겠죠? 그럼 쿼리문의 실행과정에 대해 알아볼까요?
먼저 다음과 같은 아키텍처 다이어그램을 살펴보겠습니다.
커넥터
: 다양한 언어 간의 상호 작용을 지원하는 데 사용됩니다. 및 SQL(예: PHP, Python, Java's Connector
:用来支持各种语言和 SQL 的交互,比如 PHP,Python,Java 的 JDBC;
Management Serveices & Utilities
:系统管理和控制工具,包括备份恢复、MySQL 复制、集群等;
Connection Pool
:连接池,管理需要缓冲的资源,包括用户密码权限线程等等;
SQL Interface
:用来接收用户的 SQL 命令,返回用户需要的查询结果 ;
Parser
:用来解析 SQL 语句;
Optimizer
:查询优化器;
Cache and Buffer
:查询缓存,除了行记录的缓存之外,还有表缓存,Key 缓存,权限缓存等等;
Pluggable Storage Engines
관리 서비스 및 유틸리티
: 백업 및 복구, MySQL 복제, 클러스터링 등을 포함한 시스템 관리 및 제어 도구)
연결 풀
: 연결 풀, 사용자 비밀번호 권한 스레드 등을 포함하여 버퍼링해야 하는 리소스를 관리합니다.
SQL 인터페이스
: 수신하는 데 사용됩니다. 사용자의 SQL 명령을 실행하고 사용자에게 필요한 쿼리 결과를 반환합니다.
Parser
: SQL 문을 구문 분석하는 데 사용됩니다. Optimizer
: 쿼리 최적화 프로그램; 캐시 및 버퍼
: 쿼리 캐시, 행 레코드 캐시 외에도 테이블 캐시, 키 캐시, 권한 캐시 등도 있습니다. 플러그블 스토리지 엔진 : 서비스에 API를 제공하는 플러그인 스토리지 엔진입니다. 레이어를 사용하여 특정 파일을 처리합니다.
연결 레이어
MySQL 서버 포트 3306에 연결하려면 클라이언트가 서버와의 연결을 설정한 다음 모든 연결을 관리하고 클라이언트의 신원과 권한을 확인해야 합니다. 이러한 기능은 연결 레이어에 있습니다. 완전한. 서비스 계층연결 계층은 SQL 문을 서비스 계층으로 넘겨주며, 여기에는 일련의 프로세스도 포함됩니다.
예를 들어 쿼리 캐시 판단, SQL에 따라 해당 인터페이스 호출, 어휘화 SQL 문 및 문법 분석(키워드 식별 방법, 별칭 식별 방법, 문법 오류 여부 등)
스토리지 엔진은 데이터가 실제로 저장되는 곳입니다. MySQL은 다양한 스토리지 엔진을 지원합니다. 다음은 메모리나 디스크입니다.
SQL 실행 프로세스select name from user where id=1 and age>20;
먼저 사진을 보겠습니다. 이 사진을 기반으로 다음 프로세스가 진행됩니다.
Connection데이터베이스를 운영하는 프로그램이나 도구의 첫 번째 단계는 연결을 설정하는 것입니다. 데이터베이스와 함께. 🎜🎜데이터베이스에는 두 가지 종류의 연결이 있습니다. 🎜🎜🎜짧은 연결: 짧은 연결은 작업이 완료된 후 즉시 닫히는 것을 의미합니다. 🎜🎜긴 연결: 긴 연결을 유지하여 서버 측에서 연결을 생성하고 해제하는 데 드는 비용을 줄일 수 있습니다. 이 연결은 후속 프로그램이 액세스할 때도 사용할 수 있습니다. 🎜🎜🎜연결 설정이 꽤 번거롭습니다. 요청을 보낸 후 계정 비밀번호를 확인해야 하므로 사용 중에 사용해 보세요. 긴 연결. 🎜🎜긴 연결을 유지하면 메모리가 소모됩니다. 연결이 오랫동안 비활성화되면 MySQL 서버 연결이 끊어집니다. sql 문을 사용하여 기본 시간을 볼 수 있습니다: 🎜show global variables like 'wait_timeout';🎜이 시간은 wait_timeout에 의해 제어되며 기본값은 28800초, 8시간입니다. 🎜🎜Query Cache🎜🎜MySQL에는 내부적으로 캐시 모듈이 포함되어 있습니다. 동일한 쿼리를 실행한 후 캐시가 적용되지 않는 것으로 나타났습니다. 이유는 무엇입니까? MySQL의 캐시는 기본적으로 꺼져 있습니다. 🎜
show variables like 'query_cache%';🎜Off는 기본적으로 사용을 권장하지 않음을 의미합니다. MySQL이 자체 캐시 사용을 권장하지 않는 이유는 무엇입니까? 🎜🎜주로 MySQL의 내장 캐시에는 제한된 애플리케이션 시나리오가 있기 때문입니다. 🎜🎜첫 번째는 SQL 문이 정확히 동일해야 하고 중간에 추가 공백이 있어야 하며 대소문자가 다른 문자가 고려되어야 한다는 것입니다. 다른 SQL. 🎜
第二个是表里面任何一条数据发生变化的时候,这张表所有缓存都会失效,所以对于有大量数据更新的应用,也不适合。
所以缓存还是交给 ORM 框架(比如 MyBatis 默认开启了一级缓存),或者独立的缓存服务,比如 Redis 来处理更合适。
在 MySQL 8.0 中,查询缓存已经被移除了。
为什么一条 SQL 语句能够被识别呢?假如随便执行一个字符串 hello,服务器报了一个 1064 的错:
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'hello' at line 1
这个就是 MySQL 的解析器和预处理模块。
这一步主要做的事情是对语句基于 SQL 语法进行词法和语法分析和语义的解析。
词法分析就是把一个完整的 SQL 语句打碎成一个个的单词。
比如一个简单的 SQL 语句:select name from user where id = 1 and age >20;
它会将 select
识别出来,这是一个查询语句,接下来会将 user
也识别出来,你是想要在这个表中做查询,然后将 where
后面的条件也识别出来,原来我需要去查找这些内容。
语法分析会对 SQL 做一些语法检查,比如单引号有没有闭合,然后根据 MySQL 定义的语法规则,根据 SQL 语句生成一个数据结构。这个数据结构我们把它叫做解析树(select_lex)。
就比如英语里面的语法 “我用 is , 你用 are ”这种,如果不对肯定是不可以的,语法分析之后发现你的 SQL 语句不符合规则,就会收到 You hava an error in your SQL syntax
的错误提示。
如果写了一个词法和语法都正确的 SQL,但是表名或者字段不存在,会在哪里报错? 是在数据库的执行层还是解析器?比如:select * from hello;
还是在解析的时候报错,解析 SQL 的环节里面有个预处理器。它会检查生成的解析树,解决解析器无法解析的语义。比如,它会检查表和列名是否存在,检查名字和别名, 保证没有歧义。预处理之后得到一个新的解析树。
一条SQL语句是不是只有一种执行方式?或者说数据库最终执行的SQL是不是就是我们发送的 SQL?
这个答案是否定的。一条 SQL 语句是可以有很多种执行方式的,最终返回相同的结果,他们是等价的。但是如果有这么多种执行方式,这些执行方式怎么得到的?最终选择哪一种去执行?根据什么判断标准去选择?
这个就是 MySQL 的查询优化器的模块(Optimizer)。 查询优化器的目的就是根据解析树生成不同的执行计划(Execution Plan),然后选 择一种最优的执行计划,MySQL 里面使用的是基于开销(cost)的优化器,那种执行计划开销最小,就用哪种。
可以使用这个命令查看查询的开销:
show status like 'Last_query_cost';
MySQL 的优化器能处理哪些优化类型呢?
举两个简单的例子:
1、当我们对多张表进行关联查询的时候,以哪个表的数据作为基准表。
2、有多个索引可以使用的时候,选择哪个索引。
实际上,对于每一种数据库来说,优化器的模块都是必不可少的,他们通过复杂的算法实现尽可能优化查询效率的目标。但是优化器也不是万能的,并不是再垃圾的 SQL 语句都能自动优化,也不是每次都能选择到最优的执行计划,大家在编写 SQL 语句的时候还是要注意。
优化器最终会把解析树变成一个执行计划(execution_plans),执行计划是一个数据结构。当然,这个执行计划不一定是最优的执行计划,因为 MySQL 也有可能覆盖不到所有的执行计划。
我们怎么查看 MySQL 的执行计划呢?比如多张表关联查询,先查询哪张表?在执行查询的时候可能用到哪些索引,实际上用到了什么索引?
MySQL 提供了一个执行计划的工具。我们在 SQL 语句前面加上 EXPLAIN,就可以看到执行计划的信息。
EXPLAIN select name from user where id=1;
在介绍存储引擎先来问两个问题:
1、从逻辑的角度来说,我们的数据是放在哪里的,或者说放在一个什么结构里面?
2、执行计划在哪里执行?是谁去执行?
在关系型数据库里面,数据是放在表 Table 里面的。我们可以把这个表理解成 Excel 电子表格的形式。所以我们的表在存储数据的同时,还要组织数据的存储结构,这个存储结构就是由我们的存储引擎决定的,所以我们也可以把存储引擎叫做表类型。
在 MySQL 里面,支持多种存储引擎,他们是可以替换的,所以叫做插件式的存储引擎。为什么要支持这么多存储引擎呢?一种还不够用吗?
在 MySQL 里面,每一张表都可以指定它的存储引擎,而不是一个数据库只能使用一个存储引擎。存储引擎的使用是以表为单位的。而且,创建表之后还可以修改存储引擎。
如果对数据一致性要求比较高,需要事务支持,可以选择 InnoDB。
如果数据查询多更新少,对查询性能要求比较高,可以选择 MyISAM。
如果需要一个用于查询的临时表,可以选择 Memory。
如果所有的存储引擎都不能满足你的需求,并且技术能力足够,可以根据官网内部手册用 C 语言开发一个存储引擎。(https://dev.mysql.com/doc/internals/en/custom-engine.html%EF%BC%89 )
谁使用执行计划去操作存储引擎呢?这就是执行引擎(执行器),它利用存储引擎提供的相应的 API 来完成操作。
为什么我们修改了表的存储引擎,操作方式不需要做任何改变?因为不同功能的存储引擎实现的 API 是相同的。
最后把数据返回给客户端,即使没有结果也要返回。
还是以上面的sql语句为例,再来梳理一下整个sql执行流程。
select name from user where id = 1 and age >20;
通过连接器查询当前执行者的角色是否有权限,进行查询。如果有的话,就继续往下走,如果没有的话,就会被拒绝掉,同时报出 Access denied for user
的错误信息;
接下来就是去查询缓存,首先看缓存里面有没有,如果有呢,那就没有必要向下走,直接返回给客户端结果就可以了;如果缓存中没有的话,那就去执行语法解析器和预处理模块。( MySQL 8.0 版本直接将查询缓存的整块功能都给删掉了)
语法解析器和预处理主要是分析sql语句的词法和语法是否正确,没啥问题就会进行下一步,来到查询优化器;
查询优化器就会对sql语句进行一些优化,看哪种方式是最节省开销,就会执行哪种sql语句,上面的sql有两种优化方案:
优化器决定选择哪个方案之后,执行引擎就去执行了。然后返回给客户端结果。
更多编程相关知识,请访问:编程视频!!
위 내용은 MySQL에서의 SQL 실행 과정에 대한 심층 분석(그림과 텍스트의 조합)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!