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

join查询中索引建议

一 索引选择规则

join关联查询

    对于join字段索引,被驱动表才是关键,join执行过程如下:

    1)先扫描驱动表,根据WHERE条件过滤

    2)对于驱动表的每一行,用join字段值去被驱动表查找匹配行

    3)这时需要被驱动表的join字段必须要有索引

    下面是建议原则:

     驱动表:首先要确保where条件充分利用好索引,放在联合索引最前面,join字段放在联合索引的最后,这样通过where条件过滤后不用回表就能拿到join字段的值

     被驱动表:也存在where过滤条件,join字段索引优先,where字段放在后面,这样通过join字段快速定位记录,再用where条件索引字段过滤,能用覆盖索引

 

二 测试用例

-- 创建测试数据
CREATE TABLE test_msg (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT,channel_id_type VARCHAR(10),unionid VARCHAR(100),INDEX idx_test (channel_id_type, unionid,user_id)
);CREATE TABLE test_info (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT,user_status VARCHAR(5),cert_type VARCHAR(5),INDEX idx_userid_status_cert (user_id,user_status, cert_type)  
);- 插入测试数据
INSERT INTO test_msg (user_id, channel_id_type, unionid)
SELECT n, '1', 'UNION001' 
FROM (SELECT @row := @row + 1 AS n FROM (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t1,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t2,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t3,(SELECT @row := 0) t4) numbers
LIMIT 100;INSERT INTO test_info (user_id, user_status, cert_type)
SELECT n, IF(n % 10 = 0, '1', '0'),  -- 10% 符合 user_statusIF(n % 5 = 0, '01', '02')  -- 20% 符合 cert_type
FROM (SELECT @row2 := @row2 + 1 AS n FROM (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t1,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t2,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t3,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t4,(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2) t5,(SELECT @row2 := 0) t6) numbers
LIMIT 10000;

 

用例sql1:  被驱动表使用覆盖索引

SELECT *
FROM test_msg msg
LEFT JOIN test_info info ON msg.user_id = info.user_id
WHERE msg.channel_id_type = '1'AND msg.unionid = 'UNION001'AND info.user_status = '1'AND info.cert_type = '01';

 执行计划:

image

 从执行计划看,驱动表msg和被驱动表info都走了覆盖索引

 

用例sql2:  被驱动表join字段没有索引

SELECT * 
FROM test_msg msg 
STRAIGHT_JOIN test_info info ON msg.user_id = info.user_id
WHERE msg.channel_id_type = '1'   AND msg.unionid = 'UNION001'   AND info.user_status = '1'AND info.cert_type = '01';

执行计划:

image虽然也走了索引但是过滤性只有10%,执行流程如下:

### 第二行(被驱动表 info)
```
table: info
type: ref                           ← 这里是关键!
key: idx_status_cert               ← 使用了 WHERE 条件索引
key_len: 46                        ← user_status + cert_type
ref: const,const                   ← 'const,const' 不是 'msg.user_id'!
rows: 24                           ← 预计扫描24行
filtered: 10.00                    ← 只有10%会匹配!
Extra: Using where                 ← JOIN条件在WHERE中过滤
```**关键发现:**1. **`ref: const,const`** → 使用的是 `user_status='1', cert_type='01'`
2. **不是 `ref: msg.user_id`** → 没有使用 user_id 索引查找!
3. **`filtered: 10.00`** → 只有10%的行会匹配 JOIN 条件
4. **`Extra: Using where`** → JOIN 条件 `msg.user_id = info.user_id` 是在获取数据后才过滤的---## 实际执行流程
```
步骤1:扫描 msg 表- 使用索引 idx_test 的前2列- WHERE channel_id_type='1' AND unionid='UNION001'- 得到 27 行- 从索引中读取每行的 user_id(覆盖索引)步骤2:对 msg 的 27 行,JOIN info 表┌────────────────────────────────────────────────┐│ FOR EACH row in msg (27 次循环):              ││                                                ││   1. 使用索引 idx_status_cert 扫描            ││      WHERE user_status='1' AND cert_type='01' ││      → 得到 24 行                             ││                                                ││   2. 在这 24 行中逐行检查(Using where):     ││      WHERE info.user_id = msg.user_id         ││      → 平均只有 2-3 行匹配 (filtered: 10%)   ││                                                ││   总计:每次循环读取 24 行,过滤后留 2-3 行   │└────────────────────────────────────────────────┘总扫描行数:27 × 24 = 648 行
实际匹配:27 × 2.4 ≈ 65 行

 如果 info.user_id 有索引会怎样?

CREATE INDEX idx_userid_status_cert ON test_info(user_id,user_status,cert_type
);
```### 新的执行计划
```
*************************** 2. row ***************************
table: info
type: ref
key: idx_userid_status_cert        ← 使用新索引
key_len: 50                        ← user_id + user_status + cert_type
ref: msg.user_id,const,const       ← 关键!用 msg.user_id 查找
rows: 1                            ← 每次只查1行!
filtered: 100.00                   ← 100% 匹配
Extra: Using index                 ← 覆盖索引
```### 新的执行流程
```
步骤1:扫描 msg 表- 得到 27 行步骤2:对 msg 的 27 行,JOIN info 表┌────────────────────────────────────────────────┐│ FOR EACH row in msg (27 次循环):              ││                                                ││   直接用索引查找:                             ││   WHERE user_id = msg.user_id                 ││     AND user_status = '1'                     ││     AND cert_type = '01'                      ││   → 每次最多 1 行(索引精确查找)             ││                                                │└────────────────────────────────────────────────┘总扫描行数:27 × 1 = 27 行
实际匹配:27 行
```---## 性能对比### 场景1:无 user_id 索引(当前情况)
```
驱动表:27 行
被驱动表:每次扫描 24 行 × 27 次 = 648 行扫描
WHERE 过滤:648 → 65 行(90% 被丢弃)总IO:675 行
有效数据:65 行
浪费率:90%
```### 场景2:有 user_id 索引
```
驱动表:27 行
被驱动表:每次查找 1 行 × 27 次 = 27 行查找总IO:54 行
有效数据:27 行(假设全部匹配)
浪费率:0%

性能提升:675 vs 54 → 提升 12.5 倍!而且随着数据量越大,差距越明显! 

最佳实践

JOIN 字段必须有索引! 尤其是:

  1. ✓ 被驱动表的 JOIN 列必须有索引
  2. ✓ 索引应该将 JOIN 列放在前面
  3. ✓ 推荐创建复合索引:(join_col, where_col1, where_col2)

 

http://www.jsqmd.com/news/312729/

相关文章:

  • 银川市英语雅思培训辅导机构推荐:2026权威出国雅思课程中心学校口碑排行榜
  • DCS隔膜泵数据采集物联网解决方案
  • 海鲜陆地养殖物联网远程监控系统方案
  • 网络安全黑客技术之实现了一下CSRF原来不像背的那么简单,网络安全零基础入门到精通教程!
  • CTF学习法则——寒假篇 新手赶快收藏吧!
  • 本站最全网络安全学习路线图(2026版详解版)
  • 快看 !计算机专业包括哪些专业?计算机类18个专业全面解读,附就业方向,收藏这一篇就够了
  • 2026年常州营销推广公司推荐:五大权威评测榜单与全域增长选型终极指南
  • 2026年江苏板簧/压簧/拉簧/农机弹簧/弹齿厂家选型指南:技术变革下的头部玩家与决策逻辑
  • 口碑好的管线管品牌推荐,天津腾昊伟业钢管在其中吗
  • 分析国际高中学校,上海林国荣京岛义塾学校性价比如何
  • 2026年常州营销推广公司推荐:全域增长痛点深度评测,涵盖电商与本地生活场景
  • 2026年防撞板厂家费用揭秘,佛山品牌有哪些优势
  • 2026年儿童英语学习机构排名,细数那些性价比高的儿童英语课程
  • 好用的隧道炉品牌有哪些,实力强的隧道炉企业江苏盐能值得关注
  • 2026年镜面不锈铁卷制造厂排名,这些品牌值得推荐
  • 2026年南京靠谱的工业遥控器定制制造厂排名,精度高是关键
  • 2026年杭州日料餐厅选购指南,印江户料理评价好味道正宗吗
  • 2026年去泪痕植物原料公司哪家好?宠物泪痕管理专用植物提取物TOP5厂家推荐
  • 2026年江浙沪沿海港口城市冠洁高压清洗机品牌推荐与选购指南
  • 探讨口碑不错的天井钻机厂家排名,湖南天井钻机靠谱厂家怎么选
  • Github Copilot使用指南
  • 2026年高水准芙蓉虾仁价格对比,哪家性价比更高呢
  • LLM平台选型指南:五大主流平台优缺点深度解析,小白也能轻松上手(建议收藏)
  • 【收藏不迷路】大模型学习进阶篇:避开误区,从实战到落地全攻略
  • 收藏!35岁程序员转行大模型领域:从入门到落地的全路径规划
  • 【全面收藏】Transformer架构详解:大模型(LLMs)的核心原理与应用指南
  • 网站账号太多难管理?Enterr 开源自动化工具搭建教程
  • 导师推荐9个AI论文网站,专科生轻松搞定毕业论文!
  • 旧景如故,新景盎然,南湖公园续写九江温柔时光