0

0

高效统计符合条件的活跃课程与未删除用户关联数量的 MySQL 优化方案

霞舞

霞舞

发布时间:2026-01-06 16:15:03

|

808人浏览过

|

来源于php中文网

原创

高效统计符合条件的活跃课程与未删除用户关联数量的 MySQL 优化方案

本文介绍如何通过合理设计 join 查询与针对性索引,高效统计“未被删除的用户”中、至少参与过一门“已激活且未被删除”的课程的人数,避免全表扫描与中间结果膨胀。

在处理 courses(约3000万行)、users(约3万行)和 participants(约3千行)三表关联统计时,核心目标是:快速获取满足以下全部条件的用户去重数量

  • 用户 users.deleted_at IS NULL
  • 课程 courses.active = 1 AND courses.deleted_at IS NULL
  • 关联记录 participants.participant_type = 'Eloomi\\Models\\User'
  • 且该用户通过 participants 表与上述课程存在有效绑定

直觉上,先过滤再连接(filter-before-join)比先连接后过滤(join-then-filter)更高效。MySQL 的查询优化器虽能自动重排执行顺序,但其效果高度依赖索引支持。以下是经过结构化优化的完整方案:

✅ 推荐查询写法(语义清晰 + 易于索引利用)

SELECT COUNT(DISTINCT p.participant_id)
FROM courses AS c
INNER JOIN participants AS p ON c.id = p.course_id
INNER JOIN users AS u ON p.participant_id = u.id
WHERE u.deleted_at IS NULL
  AND c.active = 1 
  AND c.deleted_at IS NULL
  AND p.participant_type = 'Eloomi\\Models\\User';

该写法明确表达了业务逻辑(三表自然关联 + 精确过滤),同时为后续索引设计提供清晰依据。

Pippit AI
Pippit AI

CapCut推出的AI创意内容生成工具

下载

✅ 关键索引设计(按执行路径逐层优化)

表名 推荐索引 说明
courses INDEX(active, deleted_at) 最优先创建。可快速定位满足 active=1 AND deleted_at IS NULL 的少量课程(即使总行数达3000万,符合条件的可能仅数千)。复合索引首列 active 支持等值筛选,第二列 deleted_at 支持 IS NULL 条件(MySQL 8.0+ 对 IS NULL 在二级索引中高效支持)。因 InnoDB 聚簇索引特性,该索引隐含包含主键 id,可直接用于 JOIN participants。
participants INDEX(course_id, participant_type, participant_id) 按 course_id(外键)升序排列,确保能用上 courses 过滤后的 id 集合快速查找;加入 participant_type 实现覆盖过滤条件,避免回表;末尾 participant_id 用于后续关联 users 表及 COUNT(DISTINCT ...) 计算。
users INDEX(id, deleted_at) 显式引导优化器使用该二级索引(而非默认主键聚簇索引)完成 p.participant_id = u.id AND u.deleted_at IS NULL 的联合查找。若发现执行计划仍走主键扫描,可添加索引提示:JOIN users AS u USE INDEX (id, deleted_at)。
? 验证索引有效性:执行 EXPLAIN FORMAT=TREE(MySQL 8.0+)或 EXPLAIN 查看实际访问类型(应为 ref 或 range,避免 ALL/index 全扫);重点关注 key 列是否命中预期索引,rows 是否显著减少。

⚠️ 注意事项与进阶建议

  • 避免子查询嵌套:如原方案中 (SELECT ... FROM courses WHERE ...) 子查询生成临时表,易引发性能瓶颈。现代 MySQL 优化器对显式 JOIN 的处理通常优于派生表。
  • COUNT(DISTINCT) 的代价:当匹配用户量极大时(如超百万),DISTINCT 去重本身有开销。若业务允许近似统计,可考虑 APPROX_COUNT_DISTINCT()(MySQL 8.0.19+)。
  • 分区与归档策略:若 deleted_at IS NOT NULL 的历史数据占比高,可对 users 和 courses 表按 deleted_at 分区,将无效数据物理隔离。
  • 应用层兜底场景:仅当数据库层优化已达极限(如 participants 表无合适索引、或 participant_type 值分布极不均衡导致索引失效),才考虑分批拉取 course_id 列表,在 PHP 中构造 WHERE course_id IN (...) 批量查询 —— 但需严格控制 IN 列表长度(建议 ≤ 1000),并启用 prepared statement 防止 SQL 注入。

✅ 总结

高效达成该统计的核心在于:以最小集合作为驱动表(courses),通过精准复合索引实现“先筛后连”,全程避免中间结果膨胀。三张表各一个针对性复合索引,配合简洁 JOIN 查询,即可在毫秒级响应大规模数据关联计数。务必通过 EXPLAIN 持续验证执行计划,并根据真实数据分布微调索引顺序。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2284

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1499

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1400

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

951

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1413

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1233

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1444

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1304

2023.11.13

java学习网站推荐汇总
java学习网站推荐汇总

本专题整合了java学习网站相关内容,阅读专题下面的文章了解更多详细内容。

6

2026.01.08

热门下载

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

精品课程

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

共48课时 | 1.7万人学习

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

共3课时 | 0.3万人学习

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

共1课时 | 785人学习

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

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