一条sql是如何执行的详解
1. SQL 解析(Parsing)
2. 查询重写(Query Rewrite)
3. 查询规划(Query Planning)
4. 查询执行(Query Execution)
5. 结果返回
示例:查询执行流程
总结
🎈边走、边悟🎈迟早会好 |
一条 SQL 查询在 PostgreSQL(以及大多数关系型数据库)中的执行过程可以分为多个阶段。每个阶段都对应特定的任务,从 SQL 解析到最终获取查询结果。以下是 SQL 查询执行过程的详细拆解:
1. SQL 解析(Parsing)
当用户提交一条 SQL 语句后,PostgreSQL 首先进入解析阶段。这个阶段主要有以下几个步骤:
- 词法分析:首先,SQL 语句被分解为单独的词法单元(tokens),如关键字、表名、列名、操作符等。
- 语法分析:接下来,解析器(parser)根据 SQL 语法规则,检查 SQL 语句是否符合 SQL 语法。例如,
SELECT
是否紧跟着字段名等。 - 语义分析:如果语法检查通过,系统会进行语义分析。例如,验证表名和列名是否存在于数据库的元数据中。
输出:在这个阶段,SQL 语句被转换为一个内部的解析树(parse tree)。
2. 查询重写(Query Rewrite)
在解析树生成后,PostgreSQL 会检查是否有任何规则(rules)适用,并根据这些规则对查询进行重写。重写规则(如视图的定义)可能会改变原始的 SQL 查询,生成新的查询树。
例如:
- 当你查询视图时,查询会被重写为对基础表的查询。
- 应用触发器或规则也可能会重写查询。
输出:生成经过重写的查询树。
3. 查询规划(Query Planning)
这个阶段,查询规划器(Query Planner)负责将重写后的查询树转换为执行计划。查询规划器会决定如何最有效地访问数据,主要涉及以下步骤:
- 候选执行计划生成:查询规划器生成多个可能的执行计划。例如:
- 使用顺序扫描(Sequential Scan)扫描表中的所有行。
- 使用索引扫描(Index Scan)根据索引快速定位数据。
- 是否需要执行连接(JOIN)操作,以及选择哪种连接算法(嵌套循环、哈希连接、归并连接)。
- 成本估算(Cost Estimation):查询规划器会为每个候选计划估算成本。成本基于以下因素:
- I/O 成本:数据从磁盘读取到内存的成本。
- CPU 成本:处理每行数据的计算成本。
- 行数估计:查询中每个步骤的结果集大小估计。
PostgreSQL 使用统计信息(如表中行的数量、索引的选择性、列的分布等)来进行成本估算。
- 选择最佳计划:根据每个执行计划的估算成本,选择成本最低的执行计划。
输出:生成最终的执行计划(execution plan),这是系统决定如何执行查询的详细步骤。
4. 查询执行(Query Execution)
一旦执行计划确定下来,查询执行器(Query Executor)开始按照计划一步步执行操作。主要的执行步骤包括:
-
扫描(Scan):执行器按照计划选择的扫描方式(如顺序扫描、索引扫描)读取数据。
- 如果是顺序扫描,则逐行读取表中的数据。
- 如果是索引扫描,则使用索引来定位特定的行。
-
过滤(Filter):对于每一行数据,执行器会根据
WHERE
子句条件进行过滤,确保仅保留符合条件的行。 -
连接(Join):如果查询涉及多个表,执行器会根据选择的连接算法(如嵌套循环连接、哈希连接)对这些表的数据进行连接处理。
-
排序(Sort)和分组(Group):如果查询要求对数据进行排序(
ORDER BY
)或分组(GROUP BY
),执行器会在获取数据后进行这些操作。 -
投影(Projection):执行器会根据
SELECT
子句中的字段选择要返回的列,并忽略未被选中的列。 -
返回结果:最终结果集根据执行计划一步步执行并返回给客户端。
5. 结果返回
执行器生成的结果集会逐行或批量地返回给客户端,直到所有匹配的记录都返回。
示例:查询执行流程
假设你有一个简单的查询:
SELECT name, salary FROM employees WHERE department_id = 10 ORDER BY salary DESC;
-
SQL 解析:
- 解析器将 SQL 拆解为标识符:
SELECT
、name
、salary
、employees
、WHERE
、department_id
、ORDER BY
、DESC
。 - 检查
employees
表是否存在,name
、salary
、department_id
是否是合法字段。
- 解析器将 SQL 拆解为标识符:
-
查询重写:
- 如果
employees
是一个视图,SQL 会被重写为查询基础表。
- 如果
-
查询规划:
- PostgreSQL 会分析是否有适合
department_id
的索引。如果有索引,可以使用索引扫描来提高效率。 - 生成多个候选计划,例如顺序扫描、索引扫描,并计算各自的成本。
- 选择成本最低的计划。假设选择了索引扫描方式。
- PostgreSQL 会分析是否有适合
-
查询执行:
- 执行器根据选择的计划,使用索引扫描从
employees
表中查找department_id = 10
的记录。 - 过滤不符合条件的行。
- 根据
salary
列对数据进行排序。
- 执行器根据选择的计划,使用索引扫描从
-
结果返回:
- 按
salary
排序后的记录逐行返回给客户端。
- 按
总结
SQL 查询的执行过程分为解析、查询重写、查询规划、查询执行和结果返回五个主要步骤。每个步骤都对应特定的任务,从解析 SQL 到最终返回结果,确保查询尽可能高效地执行
🌟感谢支持 听忆.-CSDN博客
🎈众口难调🎈从心就好 |