当前位置: 首页 > news >正文

【面试题】MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?

MySQL 中的 count 三兄弟:效率大比拼!🚀

一、快速结论(先看结论再看分析)

方式 作用 效率 一句话总结
count(*) 统计所有行数 ⭐⭐⭐⭐ 最高 我是专业的!我为统计而生
count(1) 统计所有行数 ⭐⭐⭐⭐ 同样高效 我是 count(*) 的马甲兄弟
count(列名) 统计该列非 NULL 的行数 ⭐⭐⭐ 较慢 我挑剔,我只数非空值

结论:用 count(*) 就对了!

二、代码示例:亲测三兄弟的差别

准备测试数据

-- 创建测试表
CREATE TABLE user_test (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),age INT,email VARCHAR(100)
);-- 插入测试数据(故意插入一些NULL值)
INSERT INTO user_test (name, age, email) VALUES
('张三', 25, 'zhangsan@example.com'),
('李四', NULL, NULL),
('王五', 30, 'wangwu@example.com'),
(NULL, 28, 'unknown@example.com'),
('赵六', 35, NULL);

测试查询

-- 查看表中的数据
SELECT * FROM user_test;
/*
+----+--------+------+--------------------+
| id | name   | age  | email              |
+----+--------+------+--------------------+
|  1 | 张三   |   25 | zhangsan@example...|
|  2 | 李四   | NULL | NULL               |
|  3 | 王五   |   30 | wangwu@example.com |
|  4 | NULL   |   28 | unknown@example.com|
|  5 | 赵六   |   35 | NULL               |
+----+--------+------+--------------------+
*/-- 测试1:count(*) 统计所有行数
SELECT count(*) FROM user_test;  -- 结果:5 ✅
-- 翻译:"老板,我有多少行数据?全都要!"-- 测试2:count(1) 统计所有行数  
SELECT count(1) FROM user_test;  -- 结果:5 ✅
-- 翻译:"老板,你给我个固定值1,我数有多少个1"-- 测试3:count(列名) 统计非NULL的行数
SELECT count(name) FROM user_test;  -- 结果:4 ❗(NULL的那行没算)
SELECT count(age) FROM user_test;   -- 结果:4 ❗(NULL的那行没算)
SELECT count(email) FROM user_test; -- 结果:3 ❗(两个NULL都没算)
-- 翻译:"我只数有身份证的人,黑户不算"

三、深入剖析:它们到底有啥不同?

1. 语义区别(最重要的区别!)

-- count(*) 是 SQL 标准写法
-- 意思:给我这个表有多少行数据
-- 相当于:"这个会议室有多少个座位?"-- count(1) 是 count(*) 的一种写法
-- 意思:统计有多少个1
-- 相当于:"给每个座位发个苹果,最后数苹果"-- count(列名) 是统计该列非NULL值的数量
-- 意思:这个会议室有多少人带了手机
-- 相当于:"检查每个座位,如果有人带了手机就计数"

2. 性能区别(神话与现实)

传说中的误解:

"count(1) 比 count(*) 快" ❌
"count(主键) 最快" ❌

现实真相:

MySQL 5.7 及以后版本

  • count(*)count(1) 性能完全相同
  • MySQL 优化器会把它们当作一回事

查看执行计划证明

EXPLAIN SELECT count(*) FROM user_test;
EXPLAIN SELECT count(1) FROM user_test;
EXPLAIN SELECT count(id) FROM user_test;
-- 你会看到:前两个的执行计划完全一样!

性能排序(一般情况):

  1. count(*)count(1) ⭐⭐⭐⭐⭐
  2. count(主键列) ⭐⭐⭐⭐
  3. count(非主键有索引列) ⭐⭐⭐
  4. count(非主键无索引列) ⭐⭐

为什么 count(列名) 可能更慢?

-- 假设 email 列有索引
SELECT count(email) FROM user_test;
/*
MySQL 需要:
1. 读取索引(如果该列有索引)
2. 检查每个值是否为 NULL
3. 只计数非 NULL 的如果 email 列没有索引:
1. 读取整行数据(比 count(*) 读的更多)
2. 检查 email 是否为 NULL
3. 只计数非 NULL 的
*/

3. 特殊情况分析

-- 情况1:所有列都不允许NULL
CREATE TABLE user_not_null (id INT PRIMARY KEY NOT NULL,name VARCHAR(50) NOT NULL
);
-- 这时候:count(*) = count(id) = count(name)-- 情况2:空表 vs NULL值
CREATE TABLE empty_table (id INT);
SELECT count(*) FROM empty_table;    -- 结果:0
SELECT count(id) FROM empty_table;   -- 结果:0INSERT INTO empty_table VALUES (NULL);
SELECT count(*) FROM empty_table;    -- 结果:1
SELECT count(id) FROM empty_table;   -- 结果:0 ❗

四、实际工作中的选择指南

🎯 场景1:统计总行数

-- ✅ 正确做法
SELECT count(*) FROM orders;-- ❌ 错误做法
SELECT count(order_id) FROM orders;  -- 万一有NULL呢?
SELECT count(1) FROM orders;         -- 能用,但不是标准

🎯 场景2:统计有效数据数量

-- 统计有多少用户填写了邮箱
SELECT count(email) FROM users;  -- ✅ 这个场景就该用 count(列名)-- 统计已完成订单数量(假设 status=2 是已完成)
SELECT count(*) FROM orders WHERE status = 2;  -- ✅

🎯 场景3:统计非重复值

-- 统计有多少个不同的城市
SELECT count(DISTINCT city) FROM users;  -- ✅ count + DISTINCT-- 统计有多少个城市,排除 NULL
SELECT count(DISTINCT city) FROM users;  -- DISTINCT 会自动排除 NULL

五、性能优化技巧

1. 大表优化方案

-- 方案1:使用近似值(适用于统计概览)
SELECT TABLE_ROWS 
FROM information_schema.TABLES 
WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME = 'big_table';-- 方案2:分页总数缓存(适用于列表页)
-- 第一次查询时缓存总数,后面定时更新-- 方案3:使用汇总表
CREATE TABLE stats_daily (date DATE PRIMARY KEY,user_count INT,order_count INT
);

2. 索引优化

-- 为 count(列名) 创建索引
CREATE INDEX idx_email ON users(email);-- 但注意:count(*) 不一定需要索引,InnoDB有优化

六、有趣比喻帮你记忆

🍔 汉堡店排队比喻

-- 有10个人在排队买汉堡count(*) = "队列里有10个人" ✅
count(1) = "我给每人发个号码牌,数有10个牌" ✅  
count(现金) = "只有8个人带了现金" ❗
count(会员卡) = "只有5个人有会员卡" ❗

🏫 教室点名比喻

-- 教室里有50个座位count(*) = "教室有50个座位" ✅
count(1) = "我在每个座位放本书,最后数有50本" ✅
count(学生) = "今天来了45个学生上课" ❗(空座位不算)

七、总结与最佳实践

📋 最终建议

  1. 统计总行数,一律用 count(*)

    • 这是 SQL 标准写法
    • 性能最优(MySQL有专门优化)
    • 语义最明确
  2. 统计某列非 NULL 数量,用 count(列名)

    • 这是它的本职工作
    • 不要用它统计总行数
  3. 关于 count(1)

    • 性能与 count(*) 一样
    • 但不够"标准",像方言
    • 建议统一用 count(*)
  4. 性能关键点

    • 大表避免频繁 count
    • 考虑使用缓存或汇总表
    • 为 count(列名) 的列加索引

📊 一张图看懂

count(*)       -> 总数 -> 最快 -> 推荐使用↓
count(1)       -> 总数 -> 一样快 -> 可用但不标准↓
count(主键)    -> 总数 -> 次快 -> 主键非NULL时可用↓
count(索引列)  -> 非NULL数 -> 较慢 -> 有索引时可用↓  
count(普通列)  -> 非NULL数 -> 最慢 -> 谨慎使用

记住口诀:"数总数,用星号;数非空,列名好;数字1,虽高效,不是标准别当宝" 🎯

http://www.jsqmd.com/news/333669/

相关文章:

  • 基于PLC控制的伺服电机的转速控制系统的软件设计
  • 青岛银行:激进的“扩张主义者”
  • 湘西土家族苗族自治州英语雅思培训机构推荐.2026权威测评出国雅思辅导机构口碑榜 - 苏木2025
  • 基于plc拉杆箱振动与噪音检测平台设计
  • 锦昊网络公司概况介绍,2026年它在泰州网络营销领域好用吗 - 工业品网
  • 基于plc控制自动门的设计
  • 湘西土家族苗族自治州英语雅思培训机构推荐;2026权威测评出国雅思辅导机构口碑榜 - 苏木2025
  • 郑州英语雅思培训机构推荐,2026权威测评出国雅思辅导机构排名榜 - 苏木2025
  • 合肥有认证证书的EJU课程学校有哪些推荐 - 工业推荐榜
  • 2026无水乙醇批发采购推荐指南:4大实力厂家深度测评排行榜 - 深度智识库
  • 学霸同款9个降AIGC平台 千笔AI帮你降AI率
  • 盘点2026年新风机品牌,哪个安装方便且性价比高? - mypinpai
  • (修复方案)反射型 XSS漏洞
  • 企业微信API实战:外部群推送全链路监控体系开发
  • 2026年湖南正宗螺蛳粉加盟选哪家,地道螺蛳粉加盟性价比分析 - 工业设备
  • 郑州英语雅思培训机构推荐;2026权威测评出国雅思辅导机构排名榜 - 苏木2025
  • 湘西土家族苗族自治州英语雅思培训机构推荐、2026权威测评出国雅思辅导机构口碑榜 - 苏木2025
  • 配电网的正常与故障重构中的孤岛划分技术探讨
  • 哪种网站服务器操作系统的安全性更高?
  • 2026年广州性价比高的毛绒布厂家排名,好用的品牌都有谁? - 工业品牌热点
  • 2025具身智能发展全景报告:从技术探索到场景落地,开启通用智能新征程
  • 聊聊江苏获得认可的防火密封胶制造厂,靠谱的有几家 - 工业推荐榜
  • 滑动电阻式位移传感器:工业精密测量的隐形冠军
  • 数字人民币:概念、历史、内容与发展战略!
  • Linux 调度器
  • C语言中隐藏结构体的细节-使用struct结构体封装(定义和声明分离)
  • 2026年昆明电缆电线厂家哪家好?行业五强解析+选型指南,认准真正的实力标杆 - 2026年企业推荐榜
  • <span class=“js_title_inner“>我只是想要个红字,你却送了我一套操作系统:聊聊 node_modules</span>
  • 【读书笔记】《爱因斯坦传》
  • 具身认知的机器人实现:从哲学思想到计算框架的演进路径