PHP项目统计慢跑恢复时间数据方案
"慢跑恢复时间"通常指跑步后心率恢复到静息水平所需的时间,是评估心肺功能的重要指标,下面从数据模型、PHP实现、统计分析三个层面给出完整方案。

数据表设计
CREATE TABLE `run_records` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `user_id` INT UNSIGNED NOT NULL, `run_date` DATE NOT NULL, `distance_km` DECIMAL(5,2) COMMENT '距离', `duration_sec` INT COMMENT '跑步时长(秒)', `avg_pace_sec` INT COMMENT '平均配速(秒/公里)', `avg_hr` TINYINT UNSIGNED COMMENT '平均心率', `max_hr` TINYINT UNSIGNED COMMENT '最大心率', `hr_1min` TINYINT UNSIGNED COMMENT '结束1分钟心率', `hr_2min` TINYINT UNSIGNED COMMENT '结束2分钟心率', `hr_5min` TINYINT UNSIGNED COMMENT '结束5分钟心率', `resting_hr` TINYINT UNSIGNED COMMENT '静息心率', `recovery_sec` INT COMMENT '恢复至静息+10的心率用时(秒)', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX `idx_user_date` (`user_id`, `run_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
核心PHP逻辑
计算恢复时间(心率衰减法)
class RecoveryCalculator
{
/**
* 根据心率采样点计算恢复时间
* @param array $samples [['t'=>0,'hr'=>160], ['t'=>60,'hr'=>130], ...]
* @param int $restingHr 静息心率
* @param int $buffer 允许超出静息心率的阈值,默认10
* @return array
*/
public function calculate(array $samples, int $restingHr, int $buffer = 10): array
{
$target = $restingHr + $buffer;
$recoverySec = null;
foreach ($samples as $s) {
if ($s['hr'] <= $target) {
$recoverySec = $s['t'];
break;
}
}
// 1分钟心率下降值(HRR1,心率恢复能力核心指标)
$hrAtEnd = $samples[0]['hr'] ?? 0;
$hr1min = $this->findHrAt($samples, 60);
$hrr1 = $hr1min !== null ? $hrAtEnd - $hr1min : null;
return [
'recovery_sec' => $recoverySec,
'resting_hr' => $restingHr,
'target_hr' => $target,
'hrr1' => $hrr1, // >12 为正常, <12 提示风险
];
}
private function findHrAt(array $samples, int $sec): ?int
{
foreach ($samples as $s) {
if ($s['t'] >= $sec) return $s['hr'];
}
return null;
}
}
保存记录
public function saveRecord(int $userId, array $data): int
{
$calc = (new RecoveryCalculator())->calculate(
$data['samples'],
$data['resting_hr']
);
$stmt = $this->pdo->prepare("
INSERT INTO run_records
(user_id, run_date, distance_km, duration_sec, avg_pace_sec,
avg_hr, max_hr, hr_1min, hr_2min, hr_5min, resting_hr, recovery_sec)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([
$userId, $data['run_date'], $data['distance_km'], $data['duration_sec'],
$data['avg_pace_sec'], $data['avg_hr'], $data['max_hr'],
$data['hr_1min'] ?? null, $data['hr_2min'] ?? null, $data['hr_5min'] ?? null,
$data['resting_hr'], $calc['recovery_sec'],
]);
return (int)$this->pdo->lastInsertId();
}
统计分析SQL
用户恢复能力概览
SELECT
COUNT(*) AS total_runs,
ROUND(AVG(recovery_sec), 0) AS avg_recovery,
MIN(recovery_sec) AS best_recovery,
MAX(recovery_sec) AS worst_recovery,
ROUND(AVG(hr_1min), 1) AS avg_hr1,
ROUND(AVG(resting_hr), 1) AS avg_resting_hr
FROM run_records
WHERE user_id = ? AND run_date >= DATE_SUB(CURDATE(), INTERVAL 90 DAY);
按周趋势(用于折线图)
SELECT
YEARWEEK(run_date, 1) AS week,
MIN(run_date) AS week_start,
ROUND(AVG(recovery_sec), 0) AS avg_recovery,
ROUND(AVG(distance_km), 2) AS avg_distance,
COUNT(*) AS runs
FROM run_records
WHERE user_id = ? AND run_date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
GROUP BY YEARWEEK(run_date, 1)
ORDER BY week;
恢复能力评级
function gradeRecovery(?int $sec, ?int $hrr1): string
{
// 优先用 HRR1 判断,更权威
if ($hrr1 !== null) {
if ($hrr1 >= 25) return '优秀';
if ($hrr1 >= 18) return '良好';
if ($hrr1 >= 12) return '一般';
return '偏弱(建议关注)';
}
if ($sec === null) return '数据不足';
if ($sec <= 120) return '优秀';
if ($sec <= 300) return '良好';
if ($sec <= 600) return '一般';
return '偏弱';
}
性能优化要点
| 场景 | 措施 |
|---|---|
| 数据量大 | (user_id, run_date) 联合索引;按月分表 |
| 频繁聚合 | 建立 user_recovery_stats 汇总表,每日定时任务重算 |
| 图表查询 | 加 Redis 缓存,key = recovery:trend:{user_id}:{period} |
| 实时计算 | 心率采样点存 JSON 字段,只算一次入库,避免每次重算 |
汇总表 + 定时任务
// crontab: 0 3 * * * php /path/cron/rebuild_stats.php
$sql = "
REPLACE INTO user_recovery_stats (user_id, stat_date, avg_recovery, avg_hrr1, run_count)
SELECT user_id, CURDATE(),
AVG(recovery_sec),
AVG(hr_1min - hr_at_start),
COUNT(*)
FROM run_records
WHERE run_date = DATE_SUB(CURDATE(), INTERVAL 1 DAY)
GROUP BY user_id
";
需要注意的坑
- 恢复时间定义要统一:是"心率降到静息+10"还是"降到静息的120%",全项目必须一致,否则趋势无意义。
- 静息心率动态变化:不要用固定值,建议取跑前 5 分钟或最近 7 天晨脉均值。
- 采样频率:心率带通常 1s/次,光电手表可能 5s/次,插值补齐或按最近点取值。
- 异常值过滤:恢复时间 > 30 分钟或 < 30 秒的记录应标记为可疑,排除统计。
- HRR1 比总恢复时间更可靠:医学上常用运动后 1 分钟心率下降值(HRR1),抗噪且对比性强,建议作为核心指标。
如果你能说明数据来源(心率带 / 手环 / 手动录入)和精度,我可以给出更贴合的实现细节或 ECharts 展示代码。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播