环球军事
sql编程(从一条SQL的执行顺序,理解SQL如何写才能高效)

SQL的性能不在于语法多复杂,而在于是否符合数据库的执行逻辑。一条SQL在数据库内部的执行顺序,决定了我们如何写出高效的查询。

SQL的“秘密执行顺序”

这是SQL语句在数据库内部的真实执行顺序,也是优化的核心逻辑:

1. FROM 与 JOIN     -- 确定数据来源2. WHERe            -- 初步筛选3. GROUP BY         -- 分组聚合4. HAVINg           -- 对分组后筛选5. SELECt           -- 选择字段6. DISTINCT         -- 去重7. ORDER BY         -- 排序8. LIMIT/OFFSET     -- 限制结果

记住这个顺序,你的SQL优化就成功了一半。

优化实战:让SQL按“正确顺序”工作

案例1:WHERe要尽早过滤

低效写法:

SELECT user_id, COUNT(*) FROM orders GROUP BY user_id HAVINg user_id IN (SELECt id FROM users WHERe status = 'active');-- 先对所有订单分组,再用子查询过滤

高效写法:

SELECt o.user_id, COUNT(*) FROM orders oJOIN users u ON o.user_id = u.id AND u.status = 'active'GROUP BY o.user_id;-- 先过滤活跃用户,再分组统计

原理:在FROM/JOIN阶段就过滤数据,减少后续处理的数据量。

案例2:避免在WHERe中对字段进行计算

低效写法:

SELECt * FROM orders WHERe YEAR(create_time) = 2024 AND MonTH(create_time) = 1;-- 每行都要计算YEAR()和MonTH(),无法使用索引

高效写法:

SELECt * FROM orders WHERe create_time >= '2024-01-01' AND create_time < '2024-02-01';-- 直接使用索引范围查询

案例3:JOIN的顺序优化

低效写法:

SELECt * FROM large_table lJOIN small_table s ON l.id = s.large_idWHERe l.category = 'A';-- 先对300万行的大表做JOIN

高效写法:

SELECt * FROM (SELECt * FROM large_table WHERe category = 'A') lJOIN small_table s ON l.id = s.large_id;-- 先用WHERe将大表从300万行过滤到1万行

案例4:SELECt只取需要的列

低效写法:

SELECT * FROM users WHERe age > 20 ORDER BY create_time DESC LIMIT 100;-- 读取所有字段,包括不必要的大文本字段

高效写法:

SELECt id, name, age, create_time FROM users WHERe age > 20 ORDER BY create_time DESC LIMIT 100;-- 只读取实际需要的字段

关键优化原则

1. 索引生效的黄金法则

  • 索引在WHERe、JOIN、ORDER BY阶段使用
  • 遵循最左前缀原则
  • 避免对索引列进行运算或函数处理

2. 减少中间数据集

-- 错误:产生大量中间数据SELECt * FROM (    SELECt * FROM logs WHERe level = 'ERROR') t ORDER BY time DESC LIMIT 10;-- 正确:尽早应用LIMITSELECt * FROM logs WHERe level = 'ERROR' ORDER BY time DESC LIMIT 10;

3. EXPLAIN是你的最佳工具

每个优化都要用EXPLAIN验证:

EXPLAIN SELECt u.name, COUNT(o.id) FROM users u JOIN orders o ON u.id = o.user_id WHERe u.created_at > '2024-01-01'GROUP BY u.id HAVINg COUNT(o.id) > 5;

关注:

  • type列:ALL(全表扫描)→ index → range → ref → eq_ref → const
  • rows列:估算扫描行数
  • Extra列:Using filesort、Using temporary需要警惕

实战:一条SQL的完整优化

原始查询(执行慢):

SELECt DISTINCT u.*,        (SELECT COUNT(*) FROM orders o WHERe o.user_id = u.id) as order_countFROM users uLEFT JOIN orders o ON u.id = o.user_idWHERe u.status = 'active'   AND o.amount > 1000ORDER BY u.create_time DESC;

优化步骤:

1.移除不必要的DISTINCT

SELECt u.*,        COUNT(o.id) as order_countFROM users uJOIN orders o ON u.id = o.user_id WHERe u.status = 'active'   AND o.amount > 1000GROUP BY u.idORDER BY u.create_time DESC;

2.添加合适索引

CREATE INDEX idx_users_status ON users(status);CREATE INDEX idx_orders_user_amount ON orders(user_id, amount);

3.使用覆盖索引进一步优化

SELECt u.id, u.name, u.email, u.create_time,       COUNT(o.id) as order_countFROM users uJOIN orders o ON u.id = o.user_id WHERe u.status = 'active'   AND o.amount > 1000GROUP BY u.idORDER BY u.create_time DESC;

总结:高效SQL的四个层次

  1. 基础层:正确使用WHERe提前过滤
  2. 索引层:确保查询能用上合适的索引
  3. 结构层:优化JOIN顺序和子查询
  4. 存储层:考虑分库分表、读写分离

记住:数据库是按照固定顺序执行SQL的,你的任务就是让这个执行过程尽可能高效。 每次写SQL时,心里默念执行顺序,思考如何让每一步处理的数据量最小化,这就是SQL优化的核心秘诀。

好的SQL不是复杂的SQL,而是符合数据库思维的SQL。


顶一下()     踩一下()

热门推荐

发表评论
0评