当前位置: 首页 > news >正文

关于SQL子查询的使用策略

        在 SQL 优化中,一般遵循**“非必要不使用子查询”**的原则,因为子查询可能会带来额外的计算开销,影响查询效率。但是,并不是所有子查询都需要避免,有时子查询是最优解,具体要根据实际场景选择合适的优化方式。

1、为什么尽量避免子查询?

  • 子查询可能执行多次

    • 非相关子查询(Non-correlated subquery) 执行一次

    • 相关子查询(Correlated subquery) 可能要对每一行都执行一次,严重影响性能

  • 索引可能无法生效

    • 子查询的结果通常存储在临时表中,可能导致索引失效

  • 可能引入不必要的计算

    • 许多子查询可以通过 JOINEXISTS 替代,避免重复计

2、如何优化?

(1)使用子查询

        例:

SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);

         这条SQL中,子查询会遍历 orders 表的所有数据,然后再匹配 users 表,可能导致性能下降。

         优化(使用 JOIN):

SELECT DISTINCT users.* 
FROM users 
JOIN orders ON users.id = orders.user_id;

        避免了子查询的重复执行,直接连接两个表,提高查询效率。

(2)使用 IN 子查询

        例:

SELECT * FROM products 
WHERE category_id IN (SELECT id FROM categories WHERE name = 'Electronics');

        子查询会先获取 id 列,再在 products 表中查找,可能导致索引失效。 

        优化(使用 JOIN):

SELECT p.* FROM products p
JOIN categories c ON p.category_id = c.id
WHERE c.name = 'Electronics';

        JOIN 让查询引擎直接连接表,而不是单独计算子查询,提高查询速度。

(3)使用 NOT IN

        例:

SELECT * FROM users 
WHERE id NOT IN (SELECT user_id FROM orders);

  NOT IN 可能导致索引失效,并且当 orders.user_id 里有 NULL 值时,查询结果可能不正确。

        优化(NOT EXISTS):

SELECT * FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
  • NOT EXISTS 通常比 NOT IN 更高效,因为它在找到匹配的记录时就会停止搜索,而 NOT IN 需要计算整个子查询结果。

  • 避免 NULL 值带来的问题

3、什么时候可以使用子查询? 

        虽然子查询通常会带来性能问题,但在某些情况下是合理的。

     (1)子查询返回的结果是一个固定值(如 MAX()MIN()

     (2)子查询无法用 JOIN 代替(如分组统计场景)

     (3)业务逻辑复杂,避免 JOIN 使 SQL 变得过于复杂。

       例如: 

SELECT name, price FROM products 
WHERE price = (SELECT MAX(price) FROM products WHERE category_id = products.category_id);

        这种情况下,子查询返回的是单个值,对性能影响较小。

4、总结

(1)可以优化子查询的场景:

  • IN 子查询 → JOIN

  • NOT IN 子查询 → NOT EXISTS

  • 相关子查询 → JOIN 结合 GROUP BY

(2)适合使用子查询的情况

  • 需要计算单个聚合值(如 MAX()SUM()

  • 业务逻辑导致 JOIN 过于复杂

以上就是关于子查询的相关使用策略! 

http://www.dtcms.com/a/106869.html

相关文章:

  • ​自动化网络架构搜索(Neural Architecture Search,NAS)
  • RNN模型与NLP应用——(9/9)Self-Attention(自注意力机制)
  • 1Panel 面板 宝塔面板 Ubuntu 24.04
  • 叁仟数智指路机器人是否支持远程监控和管理?
  • Rclone同步Linux数据到google云盘
  • 【SQL】MySQL进阶3:Innodb引擎结构,事务与ACID的实现
  • Apifox Helper 与 Swagger3 区别
  • 一个服务器算分布式吗,分布式需要几个服务器
  • 电子企业MES管理系统智能排产与动态调度优化
  • 化工网平台API接口开发实战:从接入到数据解析‌
  • 递归(实践版)
  • 阿里云AI Studio 2.0:拖拽搭建企业级智能客服系统
  • 信息学奥赛一本通 1611:仓库建设 | 洛谷 P2120 [ZJOI2007] 仓库建设
  • Cribl 创建路线Route
  • dubbo RPC协议
  • Unity Standard Shader 解析(二)之ForwardAdd(标准版)
  • <贪心算法>
  • 第四章、Isaacsim在GUI中构建机器人(3):添加摄像头和传感器
  • Java语言如何用AI实现文件报告的自动质检?
  • Vue3编译器深度解析:从模板编译到极致性能优化
  • 【NLP 面经 5】
  • 通过ansible+docker-compose快速安装一主两从redis+三sentinel
  • 获取最新浏览器驱动,并自动安装适配浏览器
  • 使用 Amazon Lightsail 启动并配置 WordPress 实例教程
  • LRU缓存是什么
  • DataFrame基础(不包含列删除及行相关操作)
  • error LNK2019: 无法解析的外部符号 __imp__XXXX,该符号在函数xxxxx中被引用
  • 45、Vue 中的动态组件
  • 深入理解多线程编程:从基础概念到实战应用
  • 【C++】类和对象(二)