一文讲懂SQL语法顺序与执行顺序

哎,别找借口了,听我给你讲讲我当年掉过的坑。
那一年,我刚接了一个项目,数据库查询写得乱七八糟,搞得系统慢得要命。
我想知道这个 SQL 是怎么回事。

我们先来说说写顺序。
看看你写的那段话。
前台写的是SELECT,然后是FROM,然后是JOIN,ON……这其实和写代码没什么区别,你只要理解就可以了。
比如我写一个简单的库存查询时,是按照这样的顺序写的: SELECT name, amount FROM inventory WHERE inventory = 'Beicang' ORDER BY amount DESC LIMIT 1 0;如果你这样写,别人就会明白,你就是对的。

但是执行顺序不同。
写入的顺序与数据库运行的顺序完全不同。
实际的执行顺序是:首先从FROM指定的表创建一个临时表。
例如,在我的示例中,首先从库存表创建临时表 1 因此 ON 条件链接到其他表。
比如我这里没有JOIN,就直接使用临时表 1 . WHERE条件过滤,得到临时表 2 . GROUP BY分组结果得到临时表 3 . HAVING再次显示屏幕,得到临时表 4 . 最后SELECT选择字段,得到临时表 5 . 看,执行顺序和写入顺序差别很大。

为此,我写了一个复杂的查询,想用HAVING来过滤分组结果,但结果是错误的。
比如我想查看分组后数量超过1 00的仓库,我写GROUP BY仓库HAVING COUNT() > 1 00,但是报错。
由于GROUP BY先于HAVING运行,所以HAVING必须等待GROUP BY完成分组后才能有数据。
一开始不太理解,以为SQL是按照写的顺序执行的,结果程序直接崩溃了。
后来老板急了,骂了我,我才发现。

另一个例子是 UNION。
如果写在ORDER BY前面的话写法顺序是正确的。
但实际的执行是先做两次SELECT,然后UNION,然后排序。
当我编写 UNION 时,我想连接两个查询,然后对它们进行排序。
结果写为 SELECT...UNION SELECT...ORDER BY ,不带括号。
结果的排序是合并后的整体排序,而不是每个子查询的内部排序。
数据混乱,花了一周时间才修复。

所以,按照自己的习惯写顺序就行了,知道运行顺序就可以了。
特别是在编写复杂查询时,要多次运行执行计划,看看数据库运行情况如何。
别像我当年那样,写着写着,什么也不做,到最后连你都看不懂。

对了,你还问我SQL语句的书写顺序和执行顺序是不是不一样。
其实对于初学者来说,先按照书写顺序来写,然后慢慢理解运行顺序是比较自然的。
我学习的时候,先把书写顺序背下来,然后慢慢观察执行过程,从而逐渐理解。

mysql的执行流程和执行顺序

我告诉你,MySQL的运行过程其实是相当复杂的,但是如果你想了解它,可以为你省去很多麻烦。

我们首先谈谈获取问题请求。
说白了就是客户端发给你一条SQL语句对吧?无论是PHP、Java还是任何其他语言,都以MySQL为终结。

然后,分析问题。
这一步很关键。
无论您发送什么语句,都必须首先检查它是否正确并且是否是标准 SQL 语句。
如果你犯了错误,比如漏掉标点符号或者拼错关键词,它就会杀掉你并直接报错。
这称为语法分析。
对了,2 02 2 年,我在调试代码的时候,遇到过很多这样的低级错误。
当时我真的很困惑,后来才知道是我自己写的。

分析完成后,还需要进行预处理。
这一步是做什么用的?关键是检查你提到的表是否存在,列名是否正确,以及你是否有权限检查这些表。
例如,如果您输入 SELECT FROM non_existent_table;,它会在预处理阶段被检测到,并直接告诉您该表不存在,无需进一步操作。
这样可以省去很多麻烦。
我当时正在写代码,但是因为表名拼错了,卡了很久。
后来我才发现问题所在。

下一步是查询优化。
这是MySQL的核心,尤为重要。
优化器将根据您提供的查询生成执行计划。
它会考虑到很多因素,比如表有多大,有没有索引,检查哪些列,​​如何连接表等等,这个东西是相当复杂的。
它必须计算不同的可能性并选择最快的一种。
比如你查一个有几百万行的表,如果有索引,就会使用索引。
如果没有索引,它可以扫描整个表。
2 02 2 年,我优化了一个查询,因为它使用了全表扫描,结果非常慢。
后来加上了索引,速度快了几个数量级。

生成执行计划后,就可以执行查询了。
这一步是按照计划,用真武器来核对数据。
它会在内存中查找,如果找不到,则会在磁盘上查找。
如果表上有索引,它将使用索引来加快搜索速度。
在执行过程中,还会使用缓存(例如Query Cache)来存储一些查询结果。
如果下次检查相同的语句,则可以直接访问内存,而无需再次检查。
在之前的一个项目中,我解决了很多由于Query Cache导致的慢查询,效果特别好。

最后一步是返回结果。
查询完成后,将数据打包发送给客户端。
一旦客户端收到数据,就可以将其显示或用于其他计算。

我们来谈谈执行顺序。
这已得到修复。
当你编写SQL时,你需要知道它是如何执行的。
首先是 FROM 子句,它首先定义要查看哪些表以及如何链接它们。
例如,如果您键入 SELECT FROM table1 JOIN table2 ON table1 .id = table2 .id;,它将首先处理 JOIN 并合并两个表。
2 02 2 年我在北京做的一个项目是复杂的 JOIN 会减慢数据库速度。
后来我优化了JOIN语句,速度提高了。

接下来是 WHERE 子句,用于根据条件过滤数据。
只有满足条件的行才会被删除。
例如,WHERE 年龄 > 1 8 ;只会保存年龄大于 1 8 的行。

接下来是 GROUP BY 子句对数据进行分组。
例如GROUP BY部门;按部门分组。
聚类结束后,计算聚合函数,如COUNT()、SUM(salary)。

接下来是 HAVING 子句,用于过滤分组结果。
例如,HAVING COUNT() > 1 0;只会保存分组后行数大于 1 0 的组。

最后是 SELECT 子句,它选择要返回的列。
如果有ORDER BY,则按顺序排序。
例如,ORDER BY 名称 ASC;按名称升序排序。
最后,如果有 LIMIT,则只取前 N 行。
例如,LIMIT 1 0;只会获取前 1 0 行。

看,顺序不能混淆。
WHERE 出现在 GROUP BY 之前,GROUP BY 出现在 HAVING 之前。
这是固定的。

总之,了解MySQL的执行流程和顺序可以帮助你写出更好的SQL,更快地查询。
但MySQL实际运行时,会根据情况进行优化,所以不能死记硬背,必须具体问题具体分析。

mysql的执行流程和执行顺序

上周我查看了MySQL进程。

首先获取查询语句。

然后分析。
检查语法是否正确。

检查是否有缓存。
如果之前执行的类似查询的结果仍然有效,则可以直接从缓存返回。

如果没有缓存或者无法使用缓存,则生成查询计划。

最快的执行方式是什么?使用索引还是全表扫描?选择最好的方式。

然后按计划进行。
检查数据。

测试结束后,将结果交给用户。

顺序是一般的。

首先看一下FROM子句以及检查哪个表。

再看看在哪里过滤数据。

然后GROUP BY,分组。

再次在组内进行过滤。

SELECT 选择字段。

按排序。

最后是LIMIT,数量限制。

但是当MySQL实际运行时,它会自我优化。

顺序可能会改变。

这取决于你。