0

0

mysql中优化JOIN查询的索引选择与配置

P粉602998670

P粉602998670

发布时间:2026-01-20 10:15:45

|

934人浏览过

|

来源于php中文网

原创

JOIN字段无索引会导致查询慢十倍;需为ON子句字段建B-tree单列索引,外键列不自动索引;驱动表选错引发Using join buffer;复合条件应建联合索引(t1_id, status)并注意类型一致与隐式转换。

mysql中优化join查询的索引选择与配置

JOIN字段没索引,查询直接变慢十倍

MySQL执行JOIN时,如果关联字段(比如ON t1.id = t2.t1_id中的t1.idt2.t1_id)没有索引,优化器大概率会走全表扫描。尤其当被驱动表(通常是JOIN右边的表)数据量稍大,性能断崖式下跌。不是“可能慢”,是几乎必然慢。

实操建议:

  • ON子句中出现的每个字段,单独检查是否已有索引:
    SHOW INDEX FROM table_name;
  • 若字段常用于JOIN且区分度高(如外键),优先建B-tree单列索引;不要依赖联合索引的“前缀匹配”来支撑JOIN,除非该字段恰好是联合索引最左列
  • 注意:主键自动有索引,但外键列不会自动创建索引——哪怕你加了FOREIGN KEY约束,也必须显式建索引

驱动表选错导致Extra: Using join buffer

MySQL默认用BNL(Block Nested-Loop)算法处理JOIN,当驱动表小、被驱动表大且后者无可用索引时,就会启用join_buffer。这时EXPLAIN里会出现Extra: Using join buffer,意味着大量数据被载入内存做嵌套循环,I/O和CPU压力陡增。

关键判断点:

  • EXPLAIN输出的table列顺序:排在前面的是驱动表,后面的是被驱动表
  • 确保驱动表是结果集最小的那个(不一定是物理行数最少,而是经过WHERE过滤后实际参与JOIN的行数最少)
  • STRAIGHT_JOIN强制指定驱动表顺序(仅当确认优化器选错时):
    SELECT STRAIGHT_JOIN ... FROM small_table t1 JOIN large_table t2 ON t1.id = t2.t1_id;
  • join_buffer_size调大能缓解但治标不治本;真正要解决的是让被驱动表能走索引查找(即上一条说的字段加索引)

复合条件JOIN时,联合索引怎么设计

JOIN同时带WHERE过滤(如ON t1.id = t2.t1_id WHERE t2.status = 'active'),只给t2.t1_id建单列索引往往不够。优化器可能放弃使用该索引,转而全表扫描再过滤。

短影AI
短影AI

长视频一键生成精彩短视频

下载

此时应建覆盖JOIN + WHERE条件的联合索引:

  • JOIN字段放最左(因ON匹配需最左前缀)
  • 紧接WHERE中的等值条件字段(如status
  • 最后可加SELECT中需要的其他字段,实现“索引覆盖”,避免回表
  • 示例:对t2建索引(t1_id, status, name),适用于JOIN ... ON t1.id = t2.t1_id WHERE t2.status = 'active'
  • 注意:ORDER BYGROUP BY字段若也出现在查询中,可考虑加入联合索引末尾,但需权衡写入开销

EXPLAIN中type=ALL或type=index是危险信号

EXPLAIN输出里的type字段直接反映访问类型。ALL代表全表扫描,index代表全索引扫描(仍需遍历整个索引树),这两种都说明没命中有效索引用于定位JOIN行。

排查步骤:

  • 先确认key列是否为NULL——是则肯定没走索引
  • key非空但type仍是ALLindex,常见原因是:字段类型不一致(如INT vs VARCHAR)、隐式类型转换、函数包裹字段(如ON t1.id = CAST(t2.t1_id AS SIGNED)
  • 检查字符集和排序规则是否完全一致:SHOW CREATE TABLE对比两边字段的COLLATE
  • 避免在ON字段上使用函数、表达式或LIKE '%xxx'这类无法利用索引的操作
联合索引的设计粒度、驱动表的实际大小估算、以及隐式类型转换这类细节,比“加个索引”本身更影响效果。很多慢查询修复不了,卡就卡在这里。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

664

2023.06.20

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

246

2023.06.21

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

281

2023.07.18

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

514

2023.07.19

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

255

2023.07.25

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

386

2023.08.08

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

530

2023.08.11

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

599

2023.08.14

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.8万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 804人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号