PHP:foreach循环执行缓慢,求13000行users表脚本优化方案
兄弟,你这段代码的问题简直是性能优化的反面教材啊——循环里每次都跑4次数据库查询,13000条数据的话,那就是五万多次数据库请求!数据库来回折腾这么多次,能不慢吗?我给你几个实打实的优化思路,保证能把速度提上去:
核心优化思路
1. 彻底干掉循环内的多次查询——合并成一次SQL统计
这是最关键的一步!原来的逻辑是循环每个下属ID,分别查4次统计,完全没必要。我们可以用IN语句把所有下属ID一次性传入,然后用COUNT(CASE...)在SQL里直接计算四个统计值,只需要一次数据库请求。
比如优化后的代码(搭配PDO预处理,安全又高效):
// 先确保PDO连接已经建立,$pdo是连接实例 $subordinateIds = $_SESSION['subordinates']; if (empty($subordinateIds)) { $first = $second = $third = $fourth = 0; } else { // 生成对应数量的占位符,防止SQL注入 $placeholders = implode(',', array_fill(0, count($subordinateIds), '?')); $sql = " SELECT COUNT(CASE WHEN dogs = 0 AND cats = 0 THEN 1 END) AS first_count, COUNT(CASE WHEN dogs = 1 OR cats = 1 THEN 1 END) AS second_count, COUNT(CASE WHEN dogs = 0 AND cats = 0 AND myDate > SUBDATE(NOW(), INTERVAL 1 MONTH) THEN 1 END) AS third_count, COUNT(CASE WHEN (dogs = 1 OR cats = 1) AND myDate > SUBDATE(NOW(), INTERVAL 1 MONTH) THEN 1 END) AS fourth_count FROM users WHERE id IN ($placeholders) "; $stmt = $pdo->prepare($sql); $stmt->execute($subordinateIds); $stats = $stmt->fetch(PDO::FETCH_ASSOC); $first = $stats['first_count'] ?? 0; $second = $stats['second_count'] ?? 0; $third = $stats['third_count'] ?? 0; $fourth = $stats['fourth_count'] ?? 0; }
这样不管你有多少个下属ID,只需要和数据库交互一次,直接把所有统计结果拿回来,性能提升至少是几百倍级别。
2. 给查询加合适的索引,让数据库不用全表扫
你的查询用到了dogs、cats、myDate这几个字段做筛选,还用到了id做匹配。给users表建一个复合覆盖索引:
CREATE INDEX idx_users_dogs_cats_mydate ON users (dogs, cats, myDate, id);
这个索引可以让数据库直接从索引里拿到需要的所有数据,不用回表查询原数据,查询速度会快很多。
3. 修复代码里的低级错误
我看你代码里有两个明显的bug:
$third = $thirth + $q3;这里变量名写错了,$thirth应该是$third,这会导致统计结果错误,还可能触发PHP警告,拖慢执行速度。- 第二个查询里的
(cats=1 or cats=1),这明显是笔误,应该是(dogs=1 or cats=1)吧?这个逻辑错误会导致$second的统计结果不对。
4. 换掉过时的mysql扩展
mysql_*系列函数早在PHP 5.5就被废弃了,PHP 7直接移除了这些函数。换成PDO或者mysqli,不仅更安全(支持预处理防SQL注入),性能也更好,还能避免未来的兼容性问题。
为什么原来的代码这么慢?
简单说就是N+1查询问题的升级版——你这是4*N查询!每次循环都发起4次数据库请求,数据库要反复建立连接、解析SQL、执行查询、返回结果,网络开销和数据库资源消耗都极大。改成一次查询后,这些开销直接降到最低。
内容的提问来源于stack exchange,提问作者zaziD
相关产品推荐
相关产品推荐

