mysql中连接查询中的索引优化技巧
发布时间 - 2026-01-08 00:00:00 点击率:次JOIN字段必须加索引,否则被驱动表将全表扫描;索引需建在ON子句列上,注意类型一致、最左前缀及避免函数操作。
JOIN 字段必须加索引,否则直接变全表扫描
MySQL 在执行 INNER JOIN、LEFT JOIN 等连接操作时,如果 ON 条件中的字段没有索引,优化器大概率放弃使用索引,对被驱动表做全表扫描。哪怕主表只返回 1 行,被驱动表仍可能扫几万行。
常见错误现象:EXPLAIN 结果中 type 是 ALL 或 index,rows 值远超预期,Extra 出现 Using join buffer (Block Nested Loop)。
- 索引必须建在
ON子句里实际参与比较的列上,不是SELECT列 - 复合索引要注意最左前缀:若写
ON t1.a = t2.a AND t1.b = t2.b,则t2(a,b)有效,t2(b,a)通常无效 - 关联字段类型要严格一致:比如
INT和BIGINT隐式转换会导致索引失效;VARCHAR(50)和VARCHAR(100)一般不影响,但字符集或排序规则不同(如utf8mb4_0900_as_csvsutf8mb4_gene)会拒绝走索引
ral_ci
驱动表选择影响索引是否生效
MySQL 的嵌套循环连接(Nested-Loop Join)中,先查的表叫驱动表,后查的叫被驱动表。优化器通常选小结果集作驱动表,但有时判断失误,导致本该走索引的被驱动表被迫全表扫描。
可强制指定驱动顺序:用 STRAIGHT_JOIN(仅限 INNER JOIN),把预估更小的表放在 FROM 后,大表放 JOIN 后,并确保大表的 ON 字段有索引。
SELECT STRAIGHT_JOIN a.id, b.name FROM small_table a JOIN big_table b ON a.ref_id = b.id;
- 检查
EXPLAIN的table列顺序,确认哪张是驱动表 -
rows值大的那张表,务必确保其ON字段有索引 - 避免在
ON条件中对字段做函数操作,例如ON YEAR(t1.create_time) = t2.year会让t1.create_time索引失效
覆盖索引 + JOIN 可避免回表,但需注意字段顺序
当被驱动表的查询字段全部包含在某个索引中(即覆盖索引),MySQL 就不用回主键索引捞数据,能显著减少 I/O。但这要求索引把 ON 字段放在前面,查询字段放后面。
例如:需要 SELECT b.name, b.status FROM a JOIN b ON a.bid = b.id,则推荐建索引 b(id, name, status),而不是 b(name, status, id) —— 后者无法用于 ON 匹配。
- 复合索引中,等值条件字段(
=)放最左,范围条件(>,BETWEEN)放中间,查询字段放最后 - 如果
SELECT中用了ORDER BY b.name且想避免 filesort,索引需包含name并满足排序需求(如b(id, name)可支撑ORDER BY name,但前提是id是等值过滤) -
WHERE条件里的单表过滤字段也应纳入索引,例如WHERE a.type = 1 AND b.status = 'active',则b(id, status, name)更优
多表 JOIN 时,中间表索引容易被忽略
三张及以上表连接时,MySQL 会按一定顺序执行两两 JOIN。第二步 JOIN 的“被驱动表”可能是第一步的结果集(临时表),但更多时候仍是原始物理表。很多人只给首尾两张表建索引,漏掉中间表的 ON 字段索引。
典型场景:orders JOIN order_items ON orders.id = order_items.order_id JOIN products ON order_items.product_id = products.id。这里 order_items 是中间表,它既被 orders 驱动(需 order_id 索引),又被 products 驱动(需 product_id 索引)——两个字段都得单独或联合建索引。
- 用
EXPLAIN FORMAT=TREE(MySQL 8.0+)看真实执行计划,确认每一步的驱动/被驱动关系 - 中间表上建议建联合索引,如
order_items(order_id, product_id),兼顾两个方向的 JOIN - 避免
SELECT *,尤其在多表 JOIN 中,它会放大回表和临时表开销,让索引收益打折
# mysql
# ai
# 隐式转换
# select
# format
# int
# 循环
# using
# table
# 子句
# 放在
# 建在
# 万事大吉
# 很多人
# 用了
# 要注意
# 仍是
# 会让
# 那张
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
大型企业网站制作流程,做网站需要注册公司吗?
油猴 教程,油猴搜脚本为什么会网页无法显示?
香港服务器网站推广:SEO优化与外贸独立站搭建策略
Laravel怎么使用Markdown渲染文档_Laravel将Markdown内容转HTML页面展示【实战】
Python进程池调度策略_任务分发说明【指导】
微信公众帐号开发教程之图文消息全攻略
JS经典正则表达式笔试题汇总
iOS验证手机号的正则表达式
node.js报错:Cannot find module 'ejs'的解决办法
如何在云服务器上快速搭建个人网站?
Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】
如何在万网利用已有域名快速建站?
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
青岛网站建设如何选择本地服务器?
Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法
如何在Windows 2008云服务器安全搭建网站?
QQ浏览器网页版登录入口 个人中心在线进入
Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践
如何在Ubuntu系统下快速搭建WordPress个人网站?
广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?
如何在沈阳梯子盘古建站优化SEO排名与功能模块?
网站制作软件有哪些,制图软件有哪些?
Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用
利用 Google AI 进行 YouTube 视频 SEO 描述优化
javascript中的try catch异常捕获机制用法分析
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
网站制作免费,什么网站能看正片电影?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
浅谈redis在项目中的应用
Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】
Swift中swift中的switch 语句
利用JavaScript实现拖拽改变元素大小
Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
如何在七牛云存储上搭建网站并设置自定义域名?
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载
bootstrap日历插件datetimepicker使用方法
实例解析angularjs的filter过滤器
html5怎么画眼睛_HT5用Canvas或SVG画眼球瞳孔加JS控制动态【绘制】
Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全
动图在线制作网站有哪些,滑动动图图集怎么做?
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法
Laravel观察者模式如何使用_Laravel Model Observer配置
Laravel如何为API编写文档_Laravel API文档生成与维护方法
如何在Windows虚拟主机上快速搭建网站?
昵图网官网入口 昵图网素材平台官方入口
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
创业网站制作流程,创业网站可靠吗?


ral_ci