Laravel array filtering优化:企业排名连续在位周数统计性能问题求助
企业排名连续周数统计性能优化方案
1 数据库侧计算(优先选择)
避免把全量周期数据拉到应用层处理,直接在数据库内完成统计,消除数据传输和内存遍历的冗余开销:
- 提前创建周排名快照表,按
统计年份、周数、排名三个字段建联合索引,表内冗余存储对应排名的企业ID,所有查询直接命中索引无需回表。 - 用SQL逻辑直接计算连续周数,无需逐次查询,参考伪代码如下:
-- 计算指定年份、目标排名、上周周数对应的连续在榜周数 WITH weekly_rank AS ( SELECT week_num, enterprise_id FROM week_rank_snapshot WHERE stat_year = YEAR(NOW()) AND rank = {target_rank} AND week_num <= {last_week_num} ORDER BY week_num DESC ) SELECT COUNT(*) AS continuous_weeks FROM weekly_rank r1 WHERE enterprise_id = (SELECT enterprise_id FROM weekly_rank LIMIT 1) AND NOT EXISTS ( SELECT 1 FROM weekly_rank r2 WHERE r2.week_num BETWEEN r1.week_num AND {last_week_num} AND r2.enterprise_id != r1.enterprise_id )
单条查询耗时基本可以控制在10ms以内。
2 预计算冗余存储
如果排名统计逻辑固定,不需要实时计算,直接提前把结果固化:
- 每周生成最新排名时,同步计算所有上榜企业的当前排名连续保持周数,冗余存储到排名结果表的
continuous_weeks字段中,业务查询时直接读取该字段即可,无任何额外计算开销。 - 非强实时场景可以把查询结果存入Redis缓存,过期时间设置为下一次周排名更新的时间,接口响应直接走缓存。
3 应用层优化(仅用于无法修改数据库逻辑的场景)
如果必须拉取全量数据到应用层处理,优先优化内存数据结构,不要用全量数组过滤:
- 拉取数据后直接构造双层映射结构:
Map<排名, TreeMap<周数, 企业ID>>,周数默认按倒序排列。 - 查询某排名的连续周数时,直接取对应排名的TreeMap,从最大周数(上周)向前遍历,碰到企业ID和当前企业不一致时直接终止遍历,无需遍历全量数据。按每年最多53周计算,哪怕统计TOP100的所有企业排名,总循环次数也只有5300次,耗时可以忽略。
内容的提问来源于stack exchange,提问作者shafnaz
相关产品推荐
相关产品推荐

