最直接的栏目ID计数方式是用COUNT()配合WHERE查询,如SELECT COUNT() FROM articles WHERE category_id = ?,并确保category_id有索引;批量查多个栏目时用LEFT JOIN + GROUP BY;高频读场景应加缓存字段。

用 count() 配合 WHERE 查询栏目 ID 最直接
最常用也最不容易出错的方式,就是在查文章表时加个 WHERE category_id = ?,再套一层 COUNT(*)。别先查出所有记录再用 PHP 的 count() 函数——数据一多就卡顿,还浪费内存。
示例(PDO):
$stmt = $pdo->prepare("SELECT COUNT(*) FROM articles WHERE category_id = ?");
$stmt->execute([$catId]);
$articleCount = (int) $stmt->fetchColumn();
- 确保
category_id字段有索引,否则慢得明显 - 如果栏目表和文章表是主从关系,且栏目可能无文章,
LEFT JOIN + COUNT(article.id)比子查询更稳 - 别用
SELECT *加 PHPcount(),那是新手典型性能坑
用 GROUP BY 一次性查多个栏目的文章数
后台要展示所有栏目及对应文章数时,一次查完比循环查快得多。核心是把栏目 ID 当分组依据,用 COUNT() 统计每组行数。
示例(含栏目名称):
立即学习“PHP免费学习笔记(深入)”;
SELECT c.id, c.name, COUNT(a.id) AS article_count FROM categories c LEFT JOIN articles a ON c.id = a.category_id GROUP BY c.id, c.name;
-
LEFT JOIN保证没文章的栏目也能显示,COUNT(a.id)返回 0 而不是NULL - 如果只想要有文章的栏目,改用
INNER JOIN,性能略好但结果集变小 - 字段别名
article_count建议统一命名,避免模板里写$row['COUNT(a.id)']这种不可读代码
mysqli_num_rows() 不适合计数,容易误用
有人会先 SELECT id FROM articles WHERE category_id = ?,再用 mysqli_num_rows() 获取数量——这看似简单,实则浪费:数据库返回了所有 ID,PHP 却只数行数,网络和内存全白耗。
- 除非你接下来**立刻要遍历这些文章**,否则不要这么干
- 如果只是计数,
COUNT(*)让数据库内部算,不传数据,快一个数量级 -
mysqli_num_rows()对未缓冲的结果集(比如MYSQLI_USE_RESULT)可能返回 -1,行为不稳定
缓存文章数字段能扛住高并发读
栏目页被频繁访问、文章增删不频繁时,硬查数据库不是最优解。在栏目表加个 article_count 字段,增删文章后主动更新它,读的时候直接 SELECT article_count FROM categories WHERE id = ?。
- 更新时机:发文章时
UPDATE categories SET article_count = article_count + 1 WHERE id = ?;删文章时减 1 - 注意事务:文章插入失败,栏目计数也不能加,否则数据不一致
- 如果用 Redis 缓存,记得设好过期时间或监听变更事件,不然缓存和 DB 容易对不上
num_rows、忽略缓存一致性,三个点踩中一个,后期就难收场。











