SQL 查询执行的顺序

云游道人 2025-02-02 445 阅读 0评论

在 SQL 查询中,查询的执行顺序并不是按照语句中编写的顺序执行的,实际上,SQL 的执行顺序是由数据库查询优化器决定的。理解 SQL 查询的执行顺序对调优查询性能非常重要,特别是在涉及复杂查询时。

1. SQL 查询执行的顺序

虽然 SQL 查询语句看起来是从上到下逐步执行的,但数据库会根据内部的执行计划重新安排各个部分的执行顺序。标准的 SQL 执行顺序如下:

  1. FROM: 从数据源(表、视图或连接)中检索数据。

  2. ON: 对连接条件进行过滤(如果使用了连接操作,如 JOIN)。

  3. JOIN: 执行连接操作,合并不同的数据集。

  4. WHERE: 对数据应用过滤条件,排除不符合条件的行。

  5. GROUP BY: 对数据进行分组。

  6. HAVING: 对分组后的数据应用过滤条件。

  7. SELECT: 选择并返回列,确定需要查询的字段。

  8. DISTINCT: 去除重复的行。

  9. ORDER BY: 对结果进行排序。

  10. LIMIT / OFFSET: 限制返回的结果集大小或偏移量。

注意SELECT 语句是在查询的最后阶段执行的,它是结果集返回给用户的那一部分。但数据库通常会先执行数据检索、过滤、分组等操作,再进行选择列和去重的操作。

2. 执行顺序分析

让我们通过一个具体的例子来详细分析 SQL 查询的执行顺序。

假设我们有以下 SQL 查询:

SELECT customer_id, COUNT(order_id)
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id
WHERE order_date > '2024-01-01'
GROUP BY customer_id
HAVING COUNT(order_id) > 5
ORDER BY COUNT(order_id) DESC
LIMIT 10;

执行步骤:

  1. FROM:

  • 选择 orders 表和 customers 表,确定数据源。

  • 如果查询涉及到多个表(如 JOIN),数据库会首先确定哪些表和数据源需要被读取。

  1. JOIN:

  • 执行 JOIN 操作,合并 orders 和 customers 表。这里会按照 orders.customer_id = customers.customer_id 的条件进行连接。

  1. ON:

  • 在连接操作中,会根据 ON 子句指定的连接条件,过滤出符合条件的行。

  • 此步骤实际上会应用连接的条件,决定哪些行应该被连接。

  1. WHERE:

  • 应用 WHERE 子句的过滤条件。这里是 order_date > '2024-01-01',它会过滤出满足条件的行。注意,WHERE 是过滤行的步骤,作用于连接后的数据集。

  1. GROUP BY:

  • 将符合条件的结果按 customer_id 分组。GROUP BY 会根据指定的列(此处为 customer_id)对数据进行聚合。

  1. HAVING:

  • 对 GROUP BY 后的分组数据应用过滤条件。HAVING COUNT(order_id) > 5 会保留那些订单数大于 5 的客户分组。HAVING 主要用于过滤聚合后的数据,WHERE 是用于过滤原始数据的。

  1. SELECT:

  • 执行 SELECT 子句,决定从每个分组中提取哪些列。此时,customer_id 和聚合函数 COUNT(order_id) 会被选择并返回。

  1. DISTINCT (如果存在):

  • 如果查询包含 DISTINCT 关键字,它将在这一阶段去除重复的行。

  1. ORDER BY:

  • 对结果进行排序。ORDER BY COUNT(order_id) DESC 会根据订单数降序排序返回结果。

  1. LIMIT / OFFSET:

  • 最后,应用 LIMIT 和 OFFSET 子句,限制返回结果的数量或偏移量。LIMIT 10 表示只返回前 10 条记录。

3. 为什么 SELECT 是最后执行的?

理解 SELECT 作为最后执行的操作,需要从 SQL 查询的优化角度考虑。SQL 查询的设计本意是让数据库引擎从底层开始处理数据(即从数据源提取数据、连接、过滤),直到用户需要的最终结果,这时才是数据选择的阶段。

以下是具体的原因:

  • 数据检索与过滤优先:执行计划从底层表中检索数据,并根据查询条件(WHERE)和连接条件(JOIN)过滤数据。如果在这时就进行 SELECT,将会浪费资源提取不必要的字段。

  • 聚合与分组优先:在执行 SELECT 之前,数据库需要先进行数据的分组(GROUP BY),然后根据分组的结果应用聚合函数(如 COUNT()SUM()AVG() 等)。只有在分组和聚合之后,才能知道哪些列需要被选取,并根据这些结果生成最终的输出。

  • 排序与限制:数据库通常会在生成了满足查询条件的完整结果集后,才进行排序(ORDER BY)和限制(LIMIT)操作。如果早早执行 SELECT,排序和去重可能会浪费资源。

4. 执行顺序的示例:

假设你有以下查询:

SELECT product_id, COUNT(order_id)
FROM orders
JOIN products ON orders.product_id = products.product_id
WHERE order_date > '2023-01-01'
GROUP BY product_id
HAVING COUNT(order_id) > 10
ORDER BY COUNT(order_id) DESC;

执行步骤(按顺序)

  1. FROM: 从 orders 和 products 表中获取数据。

  2. JOIN: 将 orders 表和 products 表连接起来,条件是 orders.product_id = products.product_id

  3. WHERE: 过滤出 order_date > '2023-01-01' 的记录。

  4. GROUP BY: 按 product_id 对结果进行分组。

  5. HAVING: 保留那些 COUNT(order_id) > 10 的产品。

  6. SELECT: 返回 product_id 和计算的 COUNT(order_id)

  7. ORDER BY: 按照订单数降序排列结果。

  8. LIMIT (如果有的话): 限制返回的行数。

5. 总结

  • SQL 查询的执行顺序从逻辑上与我们编写查询时的顺序不同,SQL 引擎会根据执行计划优化查询。

  • SELECT 是在查询的最后执行的,原因是查询执行计划需要先完成数据检索、连接、过滤、分组等操作,然后再根据需要选择和输出列。

  • SELECT 作为最后步骤是为了确保只有在完成所有计算和过滤后,数据库才会提取最终所需的列,从而避免无谓的计算和资源浪费。

理解 SQL 查询的执行顺序是优化 SQL 查询性能和调试复杂查询的重要基础。

喜欢就支持以下吧
点赞 0

发表评论

快捷回复: 表情:
aoman baiyan bishi bizui cahan ciya dabing daku deyi doge fadai fanu fendou ganga guzhang haixiu hanxiao zuohengheng zhuakuang zhouma zhemo zhayanjian zaijian yun youhengheng yiwen yinxian xu xieyanxiao xiaoku xiaojiujie xia wunai wozuimei weixiao weiqu tuosai tu touxiao tiaopi shui se saorao qiudale qinqin qiaoda piezui penxue nanguo liulei liuhan lenghan leiben kun kuaikule ku koubi kelian keai jingya jingxi jingkong jie huaixiao haqian aini OK qiang quantou shengli woshou gouyin baoquan aixin bangbangtang xiaoyanger xigua hexie pijiu lanqiu juhua hecai haobang caidao baojin chi dan kulou shuai shouqiang yangtuo youling
提交
评论列表 (有 0 条评论, 445人围观)

最近发表

热门文章

最新留言

热门推荐

标签列表