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

SQL语句为什么要避免使用join

文章目录

  • 前言
  • 一、为什么要减少使用join
    • 1.带来的性能消耗更高
      • 1.1.驱动表无索引的复杂度分析
      • 1.2.被驱动表无索引的复杂度分析
      • 1.3.总时间复杂度对比
    • 2.多表 JOIN 加剧数据库稳定性风险
      • 2.1.锁竞争加剧,影响并发性能
      • 2.2.优化器决策难度增加,易出 “烂执行计划”
      • 2.3.故障排查难度高
  • 二、如何在减少 JOIN 的同时满足业务需求
    • 1.数据冗余
    • 2.宽表设计
    • 3.分步骤查询


前言

在SQL优化中,减少“join”是一个优化方向。本文会给大家介绍为什么要减少join及优化措施。

一、为什么要减少使用join

1.带来的性能消耗更高

数据库执行 JOIN 时,会将多个表的记录进行 “关联匹配”,这个过程比单表查询复杂得多。可以把进行关联匹配的两张表看作驱动表和被驱动表,执行过程中被驱动表是否使用索引性能差别极大。
在分析前,先明确以下前提(基于数据库最常用的嵌套循环 JOIN算法,适用于中小表关联,也是优化器默认选择):

  • 驱动表为 T1,总数据量为 N,经 WHERE 筛选后的数据量为 M(M ≤ N);
  • 被驱动表为 T2,总数据量为 K;
  • 索引查询的时间复杂度为 O(log K)(B + 树索引,查询单条数据的平均复杂度);
  • 全表扫描的时间复杂度为 O(K)(需遍历表中所有记录)。
  • 嵌套循环 JOIN 的核心流程:1 次驱动表扫描 + M 次被驱动表匹配(每 1 条驱动表记录对应 1 次被驱动表查询)。

1.1.驱动表无索引的复杂度分析

驱动表的核心作用是 “生成外层循环的查询条件”,其扫描过程仅执行 1 次,无索引的影响仅体现在 “筛选阶段的全表扫描”,不随后续流程放大。
驱动表的复杂度分为 “筛选阶段” 和 “后续无影响阶段”:

  • 筛选阶段(获取 M 行数据):
    有索引:若筛选条件(如 T1.region = ‘北京’)有索引,复杂度为 O(log N + M)(索引定位到符合条件的范围,再读取 M 行数据);
    无索引:需全表扫描 T1 筛选出 M 行,复杂度为 O(N)(遍历所有 N 行,判断是否符合条件)。
  • 后续阶段(驱动被驱动表):驱动表筛选出 M 行后,后续仅需传递 M 个关联字段值(如 user_id),无额外计算,复杂度为 O(1)(固定成本)。
  • 总时间复杂度:驱动表无索引时,仅筛选阶段复杂度从 O(log N + M) 上升到 O(N),但 O(N) 是固定值(仅执行 1 次),不随 M(驱动表筛选后行数)或 K(被驱动表数据量)增长。

1.2.被驱动表无索引的复杂度分析

被驱动表的核心作用是 “响应 M 次匹配请求”,无索引的影响会被 M 倍放大 —— 每 1 次匹配都需全表扫描,复杂度随 M 和 K 同步增长,是 JOIN 性能恶化的核心原因。

被驱动表的复杂度集中在 “M 次匹配阶段”,直接决定总复杂度:
有索引:每次匹配通过索引查找,单次复杂度为 O(log K),M 次总复杂度为 O(M × log K);
无索引:每次匹配需全表扫描,单次复杂度为 O(K),M 次总复杂度为 O(M × K)。

1.3.总时间复杂度对比

场景被驱动表匹配阶段复杂度JOIN 总复杂度(含驱动表增长趋势
被驱动表有索引O(M × log K)O(N) + O(M × log K)随 M 线性增长,随 K 对数增长
被驱动表无索引O(M × K)O(N) + O(M × K)随 M 和 K 均线性增长(指数级恶化)

M和K都取决于数据和业务,不是我们可以控制的,但是我们可以给被驱动表要扫描的列加上索引来优化性能。

2.多表 JOIN 加剧数据库稳定性风险

2.1.锁竞争加剧,影响并发性能

JOIN 查询通常需要扫描多个表的大量数据,过程中会持有表锁或行锁的时间更长(尤其是写操作并发时),期间被扫描的行 / 表会被锁定,其他写请求(如UPDATE/DELETE)需排队等待,导致并发吞吐量下降,甚至引发死锁。

2.2.优化器决策难度增加,易出 “烂执行计划”

数据库优化器(如 MySQL 的 Cost-Based Optimizer)会根据表数据量、索引、统计信息生成 “最优执行计划”,但表数量越多(JOIN 越多),优化器的决策复杂度越高.
多表 JOIN 时,优化器需评估所有可能的 “表关联顺序”(n 表 JOIN 时有 n! 种顺序),若统计信息不准确(如数据更新后未及时ANALYZE TABLE),易选择低效的关联顺序;
极端情况下,多表 JOIN 可能导致优化器 “超时”,直接采用默认的低效计划,进一步恶化性能。

2.3.故障排查难度高

当一个包含 5 张表 JOIN 的查询执行缓慢时,排查定位问题的难度远高于单表查询。需要逐一验证 “关联字段是否有索引”“驱动表选择是否合理”“中间结果集是否过大”“是否有隐式转换” 等,而单表查询只需重点排查索引和 SQL 写法即可。

二、如何在减少 JOIN 的同时满足业务需求

1.数据冗余

可以把将高频关联字段冗余到主表。
例如:订单表(orders)高频需要 “用户名”(来自用户表user),可在orders表中新增user_name字段,在用户注册 / 改名时同步更新该字段。
优点:彻底避免 “订单 - 用户” 的 JOIN,查询速度极快;
注意:需保证冗余字段的一致性(比如说更改用户表user的“用户名”时需要同步更改订单表中冗余的user_name字段,可通过触发器、消息队列同步),适合读多写少场景。

2.宽表设计

可以提前预聚合多表数据。对于报表、统计类查询(如 “按地区统计订单量”),可通过 ETL 工具(如 Flink、DataX)将 “订单表 + 用户表 + 地区表” 的关联数据预聚合为一张宽表(如order_stat_by_region),查询时直接查宽表,无需 JOIN。
优点:查询性能提升 10 倍以上,适合非实时统计场景。

3.分步骤查询

可以用应用层关联替代SQL语句的“join”。对于数据量极大的多表关联(如 3 张表均超 1000 万行),可将查询拆分为 2 步:

  1. 先查主表(如订单表),获取关键 ID(如user_id);
  2. 用IN语句批量查询关联表(如SELECT * FROM user WHERE id IN (1,2,3…));
  3. 在应用层(如 Java 代码)用 HashMap 将结果关联。

优点:避免数据库处理大表 JOIN 的高消耗,且批量查询效率更高。

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

相关文章:

  • MATLAB学习文档(二十四)
  • 【卷积神经网络CNN】基本原理
  • Jenkins Share Library教程 —— 高级实战与最佳实践
  • 基于DNA编码与混沌系统的图像加密
  • 网站建设中的html网站页面设计图片素材
  • 【数据库】MySQL InnoDB Cluster 高可用架构部署(MGR 3节点)
  • 网站关键词选取网站开发使用软件有哪些
  • 网站建设 鼠标定制化网站开发公司
  • WebUI自动化测试:POM设计模式全解析
  • tauri 应用相关文件夹
  • 建设网站哪家便宜南昌网站排名
  • AI赋能,重塑未来招聘:深度解析易路AI人岗匹配解决方案
  • 四川网站建设的公司哪家好苏州网站建设熊掌
  • QT6中Dial、Key Sequence Edit、LCD Number 功能及用法详解
  • 为什么要创建网站公司网站建设管理
  • Tomcat核心架构与生产部署指南
  • 启闭机闸门的网站建设wp做图网站
  • 一个网站项目的价格表wordpress主题Qinmei
  • 虎扑的网站是用什么技术做的江苏免费建站
  • 做网站前景怎样国家企业年审营业执照官网
  • 开封市城乡建设局网站宁德公司做网站
  • mysql网站数据库深圳双区建设
  • 论述网站建设整个流程网站开发完整的解决方案
  • Web渗透之身份认证与访问控制缺陷(越权(水平垂直),访问控制(没有验证),脆弱验证(Cookie,JWT,Session等))
  • CoRL-2025 | SocialNav-SUB:用于社交机器人导航场景理解的视觉语言模型基准测试
  • 做优化网站是什么意思设计网络品牌营销方案思路
  • 单网页网站网站 制作公司
  • c++20|第k大-快速选择|nth_element
  • 小杰深度学习(sixteen)——视觉-经典神经网络——MobileNetV2
  • asp.net企业网站设计广州一建筑外墙脚手架坍塌