本文目录导读:

- 方案一:纯 PHP 数组/内存统计(适合单进程、内存计算)
- 方案二:MySQL 数据库统计(适合持久化、大数据量)
- 方案三:Redis 实时计数器(适合高并发、实时大屏)
- 方案四:混合方案(大数据量+复杂过滤)
- 哪种更高效?
- 判断“哪队更高效”的业务定义很重要
在PHP项目中统计“反击次数”并判断哪队更高效,通常取决于数据存储方式和统计维度,这里提供几种常见的方案,从最简单的到最高性能的,并说明各自适用场景。
纯 PHP 数组/内存统计(适合单进程、内存计算)
如果数据已经在一个大的多维数组中(例如从缓存或数据库一次性取出),直接用 array_count_values 或循环是最快的。
代码示例:
<?php
$attacks = [
['team' => 'A', 'type' => 'counter', 'time' => 12],
['team' => 'B', 'type' => 'normal', 'time' => 20],
['team' => 'A', 'type' => 'counter', 'time' => 35],
['team' => 'A', 'type' => 'counter', 'time' => 40],
['team' => 'B', 'type' => 'counter', 'time' => 55],
];
// 统计反击次数
$counterCounts = [];
$totalAttacks = [];
foreach ($attacks as $attack) {
$team = $attack['team'];
$totalAttacks[$team] = ($totalAttacks[$team] ?? 0) + 1;
if ($attack['type'] === 'counter') {
$counterCounts[$team] = ($counterCounts[$team] ?? 0) + 1;
}
}
// 计算效率(反击占比)
$efficiency = [];
foreach ($counterCounts as $team => $count) {
$efficiency[$team] = $count / $totalAttacks[$team] * 100;
}
arsort($efficiency); // 按效率降序
print_r($efficiency);
?>
效率判断: 效率高 = 反击次数 / 总进攻次数 的比例高(或者单位时间内的反击频率)。
MySQL 数据库统计(适合持久化、大数据量)
如果数据存在数据库,利用 SQL 聚合函数是最高效的,避免了在 PHP 中加载大量数据。
前提: 假设有一张 attack_log 表,含 team_id 和 attack_type 字段。
-- 统计每队反击次数和总次数,并计算效率
SELECT
team_id,
SUM(attack_type = 'counter') AS counter_attacks,
COUNT(*) AS total_attacks,
(SUM(attack_type = 'counter') / COUNT(*) * 100) AS efficiency
FROM attack_log
WHERE attack_type IN ('counter', 'normal') -- 只统计有效攻击
GROUP BY team_id
ORDER BY efficiency DESC;
PHP 调用:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->query("SELECT ..."); // 上面的SQL
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
// $results[0] 就是效率最高的队伍
优势: 数据库端完成计算,PHP只负责呈现,性能最好。
Redis 实时计数器(适合高并发、实时大屏)
如果是实时直播或需要毫秒级更新的场景,利用 Redis 的哈希和原子自增。
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 每次发生反击时,原子自增
$redis->hIncrBy('stats:counter', 'team_A', 1);
// 每次发生任意攻击时,原子自增
$redis->hIncrBy('stats:total', 'team_A', 1);
// 查询效率
$counter = $redis->hGetAll('stats:counter');
$total = $redis->hGetAll('stats:total');
foreach ($counter as $team => $cnt) {
$totalCnt = $total[$team] ?? 0;
$efficiency[$team] = $totalCnt > 0 ? $cnt / $totalCnt * 100 : 0;
}
arsort($efficiency);
?>
混合方案(大数据量+复杂过滤)
如果数据量极大(千万级)且无法全量加载,则依赖数据库索引和分区表,或者使用 Elasticsearch 按时间段聚合,PHP只负责发起查询。
哪种更高效?
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 数据量小(<10万条) | 方案一(数组) | 无网络IO,最快 |
| 数据量中等(10万-100万) | 方案二(SQL聚合) | 数据库索引优化,避免PHP内存溢出 |
| 高并发实时统计 | 方案三(Redis) | 原子操作无锁,毫秒级响应 |
| 超大数据量(千万级) | 方案四(数据库+分区/NoSQL) | 需要并行计算或预聚合 |
判断“哪队更高效”的业务定义很重要
请明确“高效”的标准:
- 反击成功率:反击次数 / 总反击尝试次数。
- 反击转化率:反击得分次数 / 反击次数。
- 反击效率值:反击次数 / 比赛时间。
建议: 如果只是统计“反击次数”本身,可以直接 ORDER BY counter DESC;如果是“反击频率”,则按上述 SQL 效率公式计算。
最推荐的做法: 使用 方案二(SQL聚合),因为它是标准做法,既高效又易于维护,且数据库优化器通常能处理得比PHP循环更好。