基于PHP实现本周/本月热门视频功能的优化方案咨询
嗨,我来帮你梳理下这个浏览量统计场景的更优解决方案~
替代单条浏览记录的高效统计方案
你担心的videoviews表存每条浏览记录导致数据暴增的问题确实很常见,在高访问量下这种方案会带来存储和查询的双重压力,下面几个方案可以完美解决这个问题:
1. 按「视频+时间维度」做聚合存储
不用每条浏览都插入新记录,而是创建一张聚合统计表,比如video_daily_views,结构示例:
id | video_id | view_count | record_date ---+----------+------------+------------ 1 | 1 | 100 | 2024-05-20 2 | 2 | 120 | 2024-05-20
- 每次用户浏览视频时,执行「更新+插入兜底」的逻辑:先尝试更新对应视频当日的
view_count(UPDATE video_daily_views SET view_count = view_count + 1 WHERE video_id = ? AND record_date = CURDATE()),如果没有找到当日记录,再插入一条初始值为1的新记录。 - 这样1000个视频每天仅产生1000条数据,相比原来的10万条,存储压力直接降到原来的1%!
2. 实时缓存+离线同步的混合策略
如果需要兼顾实时性和数据持久化,还可以分两层处理:
- 实时层:用Redis这类高性能缓存暂存实时浏览量,比如给每个视频设置
video:views:{video_id}:today的key,每次浏览就执行INCR命令,完全不会给数据库带来压力。 - 离线层:每天凌晨定时把Redis里的当日统计数据同步到
video_daily_views表;如果需要保留用户浏览明细用于后续分析,可以把Redis的明细日志异步批量写入大数据存储(比如ClickHouse),不用占用业务数据库资源。
3. 预计算多维度统计结果
如果经常需要查询周、月热门视频,可以直接基于日统计表做预计算:
- 创建
video_weekly_views、video_monthly_views表,每周/每月定时执行聚合计算(比如SELECT video_id, SUM(view_count) FROM video_daily_views WHERE record_date BETWEEN 起始日期 AND 结束日期 GROUP BY video_id),把结果写入对应的预计算表。 - 查询热门视频时直接读取预计算表,速度比实时聚合快好几倍。
4. 针对明细场景的优化方案
如果确实需要保留每条浏览的明细数据,也可以做针对性优化:
- 对
videoviews表按viewed_on字段做分区(比如按天或按月分区),查询旧数据时只扫描对应分区,清理过期数据也更高效。 - 换成时序数据库(比如InfluxDB、ClickHouse),这类数据库专门针对时间序列数据做了存储和查询优化,比传统关系型数据库更适合存储大量浏览明细。
用上面的方案,不管是查当日、本周还是本月的热门视频,都能快速得到结果,同时彻底解决数据量暴增的问题~
内容的提问来源于stack exchange,提问作者Saurabh
相关产品推荐
相关产品推荐

