文章目录
优化SQL查询之了解SQL执行顺序
SQL 查询的执行过程并非是简单的按照语句的书写顺序依次进行,而是遵循着一套特定的逻辑顺序。只有掌握了这个执行顺序,我们才能准确地分析 SQL 查询的性能瓶颈,并有针对性地进行优化。通过对 SQL 执行顺序的深入理解,我们可以更好地编写高效的 SQL 查询语句,提高数据库的响应速度,减少资源消耗,为应用程序的稳定运行和良好用户体验提供坚实的基础。
查询所用关键词主要有六个,顺序依次为 select、from、where、group by、having、order by。其中 select 和 from 为必选,其他关键词可选。
举例的SQL语句
以下面的SQL举例。
SELECT
customer id,COUNT(order_id)as total_orders,
SUM(order_amount)as total spent
FROM customers
JOIN orders
ON customers.id orders.customer_id
WHERE ORDER_DATE >= 2024-01-01'
GROUP BY customer_id
HAVING total_spent≥1ooo
ORDER BY total_spent DESC
LIMIT 10;
SQL执行顺序 - 文字解释
- FROM 子句:
- 确定数据源,即
customers
表和orders
表,并根据ON
子句中的连接条件customers.id = orders.customer_id
进行表连接操作,生成一个中间结果集。
- 确定数据源,即
- WHERE 子句:
- 对连接后的中间结果集进行筛选,只保留满足
ORDER_DATE >= '2024-01-01'
条件的行。
- 对连接后的中间结果集进行筛选,只保留满足
- GROUP BY 子句:
- 按照
customer_id
对筛选后的结果进行分组。
- 按照
- 聚合函数计算:
- 在每个分组中,计算
COUNT(order_id)
作为total_orders
,计算SUM(order_amount)
作为total_spent
。
- 在每个分组中,计算
- HAVING 子句:
- 对分组后的结果进行进一步筛选,只保留满足
total_spent≥1000
条件的分组。
- 对分组后的结果进行进一步筛选,只保留满足
- SELECT 子句:
- 从满足条件的分组结果集中选择
customer_id
、total_orders
和total_spent
列作为最终结果集的列。
- 从满足条件的分组结果集中选择
- ORDER BY 子句:
- 按照
total_spent
列降序对结果集进行排序。
- 按照
- LIMIT 子句:
- 从排序后的结果集中选取前 10 行作为最终的查询结果。
SQL执行顺序 - 图示
SQL执行顺序 - 动画演示
优化SQL查询之了解SQL执行顺序
distinct 子句会在哪个位置
distinct 子句在 SQL 查询语句中起着重要的作用,它用于去除结果集中的重复行,确保返回的结果是唯一的。distinct 子句通常会位于查询语句的第六和第七步中间,也就是在 SELECT 子句之后,ORDER BY 子句之前。
在这个位置,distinct 子句首先会在 SELECT 子句从数据库中检索出数据之后对结果集进行处理。它会检查结果集中的每一行数据,如果发现有重复的行,distinct 子句会只保留其中的一行,去除其他重复的行。这样可以确保最终返回的结果集不包含重复的数据,更加简洁和准确。
然后,在 distinct 子句处理完结果集后,如果存在 ORDER BY 子句,它会对去重后的结果集按照指定的列进行排序。
除了6个主要的关键字,还有哪些关键字
在 SQL 查询中,除了上述提到的关键字外,还有以下一些关键字:
一、聚合函数相关
SUM()
:用于计算指定列的总和。例如,SELECT SUM(salary) FROM employees;
可以计算员工表中薪资列的总和。AVG()
:计算指定列的平均值。如SELECT AVG(score) FROM exams;
计算考试成绩表中分数列的平均值。MAX()
:找出指定列的最大值。比如SELECT MAX(price) FROM products;
找出产品表中价格列的最大值。MIN()
:确定指定列的最小值。例如SELECT MIN(age) FROM students;
找出学生表中年龄列的最小值。
二、连接查询相关
JOIN
:用于连接两个或多个表。例如SELECT * FROM table1 JOIN table2 ON table1.id = table2.table1_id;
根据指定的条件将两个表连接起来。LEFT JOIN
:左连接,返回左表中的所有行以及右表中匹配的行,如果右表中没有匹配的行,则相应的列值为 NULL。RIGHT JOIN
:右连接,与左连接相反,返回右表中的所有行以及左表中匹配的行。FULL JOIN
:全连接,返回两个表中的所有行,如果没有匹配的行,则相应的列值为 NULL。
三、数据操作相关
INSERT INTO
:用于向表中插入新的数据行。例如INSERT INTO customers (name, email) VALUES ('John Doe', 'john@example.com');
向客户表中插入一条新记录。UPDATE
:更新表中的数据。如UPDATE employees SET salary = salary * 1.1 WHERE department = 'Sales';
将销售部门员工的薪资提高 10%。DELETE FROM
:删除表中的数据行。例如DELETE FROM orders WHERE order_date < '2024-01-01';
删除日期早于 2024 年 1 月 1 日的订单。
四、子查询相关
IN
:用于在 WHERE 子句中判断一个值是否在一个子查询的结果集中。例如SELECT * FROM customers WHERE customer_id IN (SELECT customer_id FROM orders WHERE total_amount > 1000);
找出在订单总金额大于 1000 的订单中的客户。EXISTS
:用于在 WHERE 子句中判断一个子查询是否返回至少一行结果。例如SELECT * FROM customers WHERE EXISTS (SELECT * FROM orders WHERE customers.customer_id = orders.customer_id);
找出有订单的客户。
五、其他关键字
LIMIT
:用于限制查询结果集的行数。例如SELECT * FROM employees LIMIT 10;
只返回员工表中的前 10 行数据。OFFSET
:与 LIMIT 一起使用,用于指定从哪一行开始返回结果。例如SELECT * FROM employees LIMIT 10 OFFSET 20;
从员工表中第 21 行开始返回 10 行数据。AS
:用于为列或表起别名。例如SELECT customer_name AS name FROM customers;
将客户表中的客户名称列起别名为 name。
总结
了解 SQL 执行顺序对于优化 SQL 查询具有重要作用:
一、明确优化方向
通过了解 SQL 执行顺序,我们能够清晰地知道查询语句中各个部分的执行先后,从而有针对性地进行优化。例如,知道 WHERE 子句在早期执行,我们可以在此处尽可能地筛选出更少的数据行,减少后续操作的数据量,提高查询效率。
二、合理使用关键字
- 对于必选的关键字如 SELECT 和 FROM,我们可以根据执行顺序更好地理解它们的基础作用。SELECT 确定要返回的列,而 FROM 指明数据的来源表。在优化时,可以精心选择返回的列,避免不必要的列加载,减少数据传输和处理的开销。
- 对于可选关键字如 WHERE、GROUP BY、HAVING 等,了解执行顺序有助于我们正确地放置条件和聚合操作。WHERE 子句先于 GROUP BY 和 HAVING 执行,可以在早期阶段过滤数据。GROUP BY 用于对数据进行分组,而 HAVING 则在分组后对结果进行筛选。合理安排这些关键字的使用,可以减少不必要的分组和筛选操作,提高查询性能。
三、准确放置 distinct 子句
知道 distinct 子句在 SELECT 子句之后、ORDER BY 之前的位置,可以更好地理解其作用范围。在优化时,可以根据具体需求考虑是否使用 distinct 以及放置的位置,避免不必要的去重操作或者确保正确的去重结果。
四、充分利用其他关键字
除了六个主要关键字,了解其他关键字如聚合函数(SUM、AVG 等)、连接查询关键字(JOIN、LEFT JOIN 等)、数据操作关键字(INSERT INTO、UPDATE、DELETE FROM)和子查询相关关键字(IN、EXISTS)等的作用和执行顺序,可以在复杂查询中合理运用这些关键字,实现更高效的查询。例如,在连接查询中,根据执行顺序选择合适的连接方式可以减少数据冗余和提高查询速度。
五、整体规划查询
了解 SQL 执行顺序有助于我们从整体上规划 SQL 查询,避免不必要的操作和错误的逻辑顺序。可以根据执行顺序逐步分析查询的性能瓶颈,并采取相应的优化措施,如添加合适的索引、调整查询逻辑、优化数据存储等,以提高 SQL 查询的效率和性能。