You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL Inner Join COUNT查询性能优化求助:SQL执行耗时3分钟

SQL查询优化方案(耗时3分钟)

原查询语句

select COUNT(b.register_no)
from table1 a
         INNER JOIN table2 b ON a.register_no = b.register_no
         INNER JOIN table3 c ON a.register_no = c.register_no
    AND b.card_no = c.card_no;

基础信息

  • 各表数据量:Table1有200万条数据,Table2有250万条数据,Table3有400万条数据
  • 执行计划(EXPLAIN):
表名类型额外信息
table2index使用条件;使用索引
table3ref使用条件
table1eq_ref使用索引

1. 优化索引策略

  • 给table2创建联合索引(register_no, card_no):当前执行计划显示table2是全索引扫描,这个联合索引可以让查询直接通过register_no匹配关联条件,同时后续和table3关联时能直接用索引里的card_no过滤,避免全索引遍历,实现覆盖索引查询。
  • 给table3创建联合索引(register_no, card_no):和table2的索引逻辑一致,让a.register_no = c.register_no和b.card_no = c.card_no两个关联条件都能命中索引,提升匹配效率。
  • 确认table1的register_no是主键或唯一索引(执行计划显示eq_ref,大概率已满足),保证关联时的快速定位。

2. 调整关联逻辑与顺序

  • 尝试先关联数据量较小的表,缩小中间结果集后再关联大表,比如先关联table1和table2,再和table3关联:
SELECT COUNT(t.register_no)
FROM (
    SELECT b.register_no, b.card_no
    FROM table1 a
    INNER JOIN table2 b ON a.register_no = b.register_no
) t
INNER JOIN table3 c ON t.register_no = c.register_no AND t.card_no = c.card_no;
  • 如果table2和table3中register_no+card_no的重复数据较多,可以先对这两个表去重再关联,减少关联次数(注意:如果业务需要统计所有匹配行数,不要加DISTINCT):
SELECT COUNT(b.register_no)
FROM table1 a
INNER JOIN (SELECT DISTINCT register_no, card_no FROM table2) b ON a.register_no = b.register_no
INNER JOIN (SELECT DISTINCT register_no, card_no FROM table3) c ON a.register_no = c.register_no AND b.card_no = c.card_no;

3. 更新表统计信息

  • 执行ANALYZE TABLE table1, table2, table3;(以MySQL为例),更新数据库的表统计信息,让优化器能生成更精准的执行计划,避免因为统计信息过时导致的低效关联顺序。

4. 验证计数逻辑

  • 确认是否需要统计所有匹配的行数,还是只需要统计唯一的register_no数量。如果是后者,直接用COUNT(DISTINCT b.register_no)替代COUNT(b.register_no),可以减少计数时的运算量(前提是业务逻辑允许)。

内容的提问来源于stack exchange,提问作者KillerTwo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 05:24:17