Home  >  Article  >  Database  >  How is the select query statement executed in mysql learning?

How is the select query statement executed in mysql learning?

WBOY
WBOYforward
2022-01-06 17:17:232752browse

This article brings you relevant knowledge about the execution of select statements in mysql, including connectors, analyzers, optimizers and executors. I hope it will be helpful to everyone.

How is the select query statement executed in mysql learning?

# As a relational database, mysql should be the most widely used in China. Maybe your company uses Oracle, PG, etc., but most Internet companies, such as our company, use Mysql the most, and its importance is self-evident.

Execute select * from table, what exactly happens at the bottom of the database? So how do we get the data?

Suppose now I have a user table with only two columns, one column with an id that is incremented by itself, and one column with a name of varchar type. The table creation statement is like this:

CREATE TABLE IF NOT EXISTS `user`(
   `id` INT UNSIGNED AUTO_INCREMENT,
   `name` VARCHAR(100) NOT NULL,
   PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

The problem is the execution process of the following statement.

select * from user where id = 1;

01 Overview of mysql architecture

To understand this problem, you must know the internal architecture of mysql. To this end, I drew a mysql architecture diagram (you can also understand it as the execution process of sql query statements), as shown below:

How is the select query statement executed in mysql learning?

First of all, msql is divided into the server layer and storage engine layer. The server layer includes four functional modules: connector, query cache, optimizer, and executor. This layer is responsible for all the core work of mysql, such as built-in functions, stored procedures, triggers, views, etc.

The storage engine layer is responsible for data access. Note that the storage engine is optional in mysql. Common ones include: InnoDB, MyISAM, Memory, etc. The most commonly used one is InnoDB. It is also the default storage engine now (starting from mysql version 5.5.5). You can see that my table creation statement above specified the InnoDB engine. Of course, it will default to it if you don't specify it.

Since the storage engine is optional, all storage engines in mysql actually share a server layer. Back to the topic, let’s use the process in this picture to solve the problem of little fat.

1.1 Connector

First of all, if the database wants to execute sql, it must be connected to the database first. This part of the work is done by the connector. It is responsible for verifying account passwords, obtaining permissions, managing the number of connections, and finally establishing a connection with the client. The mysql link database is written like this:

mysql -h 127.0.0.1 -P 3306 -u root -p
# 127.0.0.1 : ip 3306 : 端口 root : 用户名

You need to enter the password after running the command, of course, you can also follow -p. However, this is not recommended as there is a risk of password leakage.

After entering the command, the connector authenticates your identity based on your account name and password. There will be two situations:

  • The account or password is incorrect, and the server will return "ERROR 1045 (28000): Access denied for user 'root'@'127.0.0.1' (using password: YES)" error, exit the connection.

  • If the verification is successful, the connector will go to the permission table to find out your permissions. What permissions you have later will be judged by the permissions read at this time.

Note, I am talking about the permissions found at this time. Even if you use the administrator account to modify the permissions of the current user, the current connected user will not be affected. You must restart mysql for the new permissions to take effect.

1.1.1 Check the connection status

The connection is completed. If nothing is done subsequently, the connection will be in an idle state. You can use the show processlist; command to view the connection information of mysql, as shown below. All my database connections are in Sleep state, except for the connections that perform the show processlist operation.

How is the select query statement executed in mysql learning?

1.1.2 Control connection

If the client does not operate for too long, the connection will be automatically disconnected. This time defaults to 8 hours and is controlled by the parameter wait_timeout. If you continue to operate after disconnecting, you will receive the error "Lost connection to MySQL server during query". At this time, you must reconnect to execute the request.

There are long and short connections in the database. Long connection: If there are continuous requests after the connection is successful, the same connection will always be used. Short connection: The connection is disconnected after executing several requests and needs to be reestablished next time.

Since establishing a connection is a time-consuming operation, it is recommended to use a long connection. But there is a problem. If a long connection remains connected, it will occupy too much memory and be forcibly sanded by the system. This causes MySQL to restart abnormally. How to solve it? Two methods:

  • Disconnect long connections regularly. Use a specific time, or the program determines that the connection is disconnected after performing an operation that takes up a lot of memory. Reconnect if necessary.

  • mySQL 5.7 or above, you can execute mysql_reset_connection to reconnect the resource after each execution of an operation that takes up a lot of memory. At this time, there is no need to reconnect or perform permission authentication again. But the connection status will be restored to when it was just created.

1.2 查询缓存

连接建立以后可以执行 select 语句了。这就会来到第二步:查询缓存。

查询缓存中存储的数据是 key-value 的形式,key 是查询语句,value 是查询的结果。逻辑是这样的:先看看查询缓存有没该语句对应的 value?有则直接取出返回客户端,无则继续到数据库执行语句。查出结果后会放一份到缓存中,再返回客户端。

你可能发现缓存真的香,但是并不建议使用查询缓存,因为有弊端。查询缓存的失效非常频繁,只有某个表有更新。它马上失效了,对于经常更新的表来说,命中缓存的概率极低。它仅仅适用于那些不经常更新的表。

而 MySQL 似乎也考虑到这点了。提供了 query_cache_type 参数,把它设置为 DEMAND 就不再适用韩村。而对于要使用缓存的语句则可用 SQL_CACHE 显示指定,像这样:

select SQL_CACHE * from user where id = 1;

PS:MySQL 8.0 及以上版本把查询缓存删掉了,之后再也没有这块功能了。

1.3 分析器

如果没有命中缓存就进入分析器,这里就是对 sql 进行分析。分析器会做词法分析。你输入的 sql 是啥,由啥组成,MySQL 都需要知道它们代表什么。

首先根据 "select" 识别出这是查询语句。字符串"user"识别成"表名 user"、字符串"id"识别成"列名id"。

之后进行语法分析,它会根据输入的语句分析是不是符合 MySQL 的语法。具体表现就是 select、where、from 等关键字少了个字母,明显不符合 MySQL 语法,这次就会报个语法错误的异常:它一般会提示错误行数,关注"use near"后面即可。

How is the select query statement executed in mysql learning?

1.4 优化器

过了分析器,就来到了优化器。MySQL 是个聪明的仔,再执行之前会自己优化下客户端传过来的语句,看看那种执行起来不那么占内存、快一点。比如下面的 sql 语句:

select * from user u inner join role r on u.id = r.user_id where u.name = "狗哥" and r.id = 666

它可以先从 user 表拿出 name = "狗哥" 记录的 ID 值再跟 role 表内连接查询,再判断 role 表里面 id 的值是否 = 666

也可以反过来:先从 role 表拿出 id = 666 记录的 ID 值再跟 user 表内连接查询,在判断 user 表里面的 name 值是否 = "狗哥"。

两种方案的执行结果是一样的,但是效率不一样、占用的资源也就不一样。优化器就是在选择执行的方案。它优化的是索引应该用哪个?多表联查应该先查哪个表?怎么连接等等。

1.5 执行器

分析器知道了做啥、优化器知道了应该怎么做。接下来就交给执行器去执行了。

开始执行,判断是否有相应的权限。比如该账户对 user 表没权限就返回无权限的错误,如下所示:

select * from user where id = 1;
ERROR 1142 (42000): SELECT command denied to user 'nasus'@'localhost' for table 'user'

PS:如果命中缓存没走到执行器这里,那么在返回查询结果时做权限验证。

回到正题,如果有权限,继续打开表执行。执行器会根据表定义的引擎去使用对应接口。比如我们上面的 sql 语句执行流程是这样的:

  • 走 id 索引、调用 InnoDB 引擎取"满足条件的第一行"接口,再循环调用"满足条件的下一行"接口(这些接口都是存储引擎定义好的),直到表中不再有满足条件的行。执行器就将上述遍历得到的行组成结果集返回给客户端。

  • 对于 id 不是索引的表,执行器只能调用"取表记录的第一行"接口,再判断 id 是否 = 1。如果不是则跳过,是则存在结果集中;再调存储引擎接口取"下一行",重复判断逻辑,直到表的最后一行。

至此,整个 SQL 的执行流程完毕,

推荐学习:mysql视频教程

The above is the detailed content of How is the select query statement executed in mysql learning?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.im. If there is any infringement, please contact admin@php.cn delete