# Promotion-List接口性能优化 ## 任务概述 修复 Promotion-List 接口的严重性能问题,该接口在查询推广团队成员列表时出现超时,执行时间超过2分钟。 ## 任务时间 - **开始时间**:2025年07月05日 00:09:24 CST - **完成时间**:2025年07月05日 00:15:00 CST - **总耗时**:约6分钟 ## 问题分析 ### 1. 问题现象 - 请求:`Promotion-List`,参数:`{"page":{"page":"2","perPage":"10"},"level":"1"}` - 执行时间:141168ms(约2.5分钟) - 最终超时失败:`cURL error 28: Operation timed out after 30002 milliseconds` - 日志显示大量SQL查询:`select urs_user_id from kku_urs_promotion_user_referrals where urs_referrer_id = ? and status = 1` ### 2. 根本原因 **性能瓶颈在 `getTeamMemberData` 方法**: 1. 第146行调用 `UrsReferralService::getTeamMembers($ursUserId)` 无参数,默认查询20代 2. 即使用户只要1代数据(level=1),系统还是查询了20代所有数据 3. `getTeamMembers()` 方法使用递归查询,对每个用户都调用 `getDirectReferrals()` 4. 产生数百次数据库查询,造成性能爆炸 ### 3. 逻辑问题 ```php // 问题代码 $teamMembers = UrsReferralService::getTeamMembers($ursUserId); // 查询20代 if ($level == 1) { // 只使用1代数据,其他19代查询都是浪费 $filteredMembers = $teamMembers[1]; } ``` ## 解决方案 ### 1. 使用缓存表优化查询 将递归查询改为使用 `UrsUserRelationCache` 缓存表: **优化前**: ```php // 递归查询20代,产生数百次SQL查询 $teamMembers = UrsReferralService::getTeamMembers($ursUserId); ``` **优化后**: ```php // 直接查询缓存表,只查询指定层级 $query = UrsUserRelationCache::where('related_user_id', $farmUserId); if ($level == 1) { $query->where('depth', 1); // 只查询1代 } ``` ### 2. 数据库层面分页 **优化前**:查询所有数据后在内存中分页 **优化后**:在数据库层面进行分页查询 ### 3. 精确查询层级 根据 `level` 参数精确查询指定层级,避免不必要的数据查询。 ## 修改内容 ### 1. 核心方法重构 文件:`app/Module/AppGame/Handler/Promotion/ListHandler.php` **主要修改**: - 重构 `getTeamMemberData()` 方法 - 使用 `UrsUserRelationCache` 缓存表替代递归查询 - 根据 `level` 参数精确查询指定层级 - 在数据库层面进行分页 - 移除不再使用的导入 **关键查询优化**: ```sql -- 统计总数 SELECT COUNT(*) FROM kku_urs_promotion_user_relation_cache WHERE related_user_id = ? AND depth = ? -- 分页查询 SELECT * FROM kku_urs_promotion_user_relation_cache WHERE related_user_id = ? AND depth = ? ORDER BY depth ASC, user_id ASC LIMIT ? OFFSET ? ``` ## 性能提升 ### 1. 执行时间对比 - **优化前**:141168ms(约2.5分钟) - **优化后**:3717ms(约3.7秒) - **性能提升**:约 **38倍** ### 2. SQL查询对比 - **优化前**:数百次递归查询 `urs_promotion_user_referrals` 表 - **优化后**:2次查询 `urs_promotion_user_relation_cache` 表(count + select) ### 3. 资源消耗 - **优化前**:大量数据库连接和查询,内存占用高 - **优化后**:最小化数据库查询,内存占用低 ## 测试验证 ### 1. 功能测试 使用 `php artisan debug:reproduce-error 69223552` 重放原始请求: - ✅ 请求成功返回 - ✅ 数据正确:total=54,返回第2页10条数据 - ✅ 分页信息正确:currentPage=2, perPage=10, hasMore=true, lastPage=6 ### 2. 性能测试 - ✅ 执行时间从141秒降低到3.7秒 - ✅ SQL查询从数百次降低到2次 - ✅ 无超时错误 ## 技术要点 ### 1. 缓存表设计 `UrsUserRelationCache` 表的设计很好地支持了这种查询优化: - `related_user_id`:上级用户ID,用于查询某用户的所有下级 - `depth`:层级深度,支持精确查询指定层级 - 索引优化:支持高效的分页查询 ### 2. 查询策略 - 避免N+1查询问题 - 使用数据库层面的分页和排序 - 根据业务需求精确查询,避免过度查询 ### 3. 向后兼容 - 保持API接口不变 - 返回数据格式完全一致 - 不影响其他功能模块 ## 业务影响 ### 1. 用户体验提升 - 推广列表加载速度大幅提升 - 避免接口超时导致的用户体验问题 - 提高系统响应性能 ### 2. 系统稳定性 - 减少数据库压力 - 降低系统资源消耗 - 提高并发处理能力 ### 3. 可扩展性 - 为后续功能扩展奠定基础 - 缓存表设计支持更复杂的查询需求 ## 提交记录 **Commit**: eb917d51 ``` 优化Promotion-List接口性能:使用缓存表替代递归查询 - 修改getTeamMemberData方法,使用UrsUserRelationCache缓存表查询 - 避免递归调用getTeamMembers方法查询20代数据的性能问题 - 根据level参数精确查询指定层级,避免不必要的数据查询 - 在数据库层面进行分页,提升查询效率 - 性能提升约38倍:从141秒优化到3.7秒 - 移除不再使用的UrsReferralService和AccountService导入 ``` ## 后续建议 ### 1. 监控优化效果 - 持续监控 Promotion-List 接口的性能表现 - 关注缓存表的数据一致性 ### 2. 类似问题排查 - 检查其他使用 `UrsReferralService::getTeamMembers()` 的地方 - 评估是否需要类似的优化 ### 3. 缓存表维护 - 确保 `UrsUserRelationCache` 表的数据及时更新 - 监控缓存表的数据完整性