news 2026/4/16 16:10:59

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【面试题】MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?

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

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

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

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

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

准备测试数据

/* by 01130.hk - online tools website : 01130.hk/zh/shaoshuminzu.html */ -- 创建测试表 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);

测试查询

/* by 01130.hk - online tools website : 01130.hk/zh/shaoshuminzu.html */ -- 查看表中的数据 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; -- 结果:0 INSERT 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,虽高效,不是标准别当宝"🎯

❤️ 如果你喜欢这篇文章,请点赞支持! 👍 同时欢迎关注我的博客,获取更多精彩内容!

本文来自博客园,作者:佛祖让我来巡山,转载请注明原文链接:https://www.cnblogs.com/sun-10387834/p/19452600

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 7:42:40

Vue-路由懒加载与组件懒加载

前言 在构建大型单页应用(SPA)时,JavaScript 包体积(Bundle Size)往往会随着业务增长而膨胀,导致首屏加载缓慢、白屏时间长。懒加载(Lazy Loading) 是解决这一问题的核心方案。其本质…

作者头像 李华
网站建设 2026/4/16 13:58:46

AI 智能体营销与餐厅结合

AI 智能体营销与餐厅结合 深圳刺身配送 - 新号启动内容策略项目背景用户激活四阶段模型第一阶段:认识→认知(价值同步)核心问题需要回答的6个问题第一阶段内容规划(发布顺序)内容1:痛点唤醒内容2&#xff1…

作者头像 李华
网站建设 2026/4/16 7:44:33

深度剖析!十五五时期职业教育发展的 4 大核心发展要点

一、"十五五"时期职业教育发展的时代要求 "十五五"时期(2026—2030年)是我国迈向2035年远景目标、推动高质量发展取得新突破的关键阶段。《建议》聚焦全局性、长远性重大问题作出系统部署,可从三个维度把握职业教育面临…

作者头像 李华
网站建设 2026/4/15 20:47:00

视频转GIF表情怎么弄?在线一键转换,高清流畅无水印

聊天斗图、社群互动、朋友圈整活、自媒体趣味配图,都离不开好用的GIF表情。相比于网上千篇一律的现成表情包,把喜欢的视频片段转成GIF表情,更有个性、更贴合场景,也更容易成为爆款斗图素材。但自己做视频转GIF表情时,很…

作者头像 李华
网站建设 2026/4/16 7:43:49

基于PLC控制的伺服电机的转速控制系统的软件设计

基于PLC控制的伺服电机转速控制系统的软件设计 第一章 绪论 伺服电机转速精准控制是工业自动化设备的核心技术需求,传统伺服电机转速控制多采用专用控制器或简易PLC逻辑,存在转速调节响应滞后、抗干扰能力弱、适配性差等问题,难以满足高精度…

作者头像 李华
网站建设 2026/4/16 7:42:26

基于PLC和组态软件的智能停车场收费系统模拟与实现

基于PLC和组态软件的智能停车场收费系统模拟与实现 第一章 绪论 智能停车场收费系统是城市交通与物业管理的核心配套设施,传统停车场收费多依赖人工计费、手动抬杆,存在计费误差大、通行效率低(单车道通行耗时≥20秒)、数据统计…

作者头像 李华