MySQL 中 count(*)、count(1) 和 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, zhangsanexample.com), (李四, NULL, NULL), (王五, 30, wangwuexample.com), (NULL, 28, unknownexample.com), (赵六, 35, NULL);测试查询-- 查看表中的数据 SELECT * FROM user_test; /* -------------------------------------- | id | name | age | email | -------------------------------------- | 1 | 张三 | 25 | zhangsanexample...| | 2 | 李四 | NULL | NULL | | 3 | 王五 | 30 | wangwuexample.com | | 4 | NULL | 28 | unknownexample.com| | 5 | 赵六 | 35 | NULL | -------------------------------------- */ -- 测试1count(*) 统计所有行数 SELECT count(*) FROM user_test; -- 结果5 ✅ -- 翻译老板我有多少行数据全都要 -- 测试2count(1) 统计所有行数 SELECT count(1) FROM user_test; -- 结果5 ✅ -- 翻译老板你给我个固定值1我数有多少个1 -- 测试3count(列名) 统计非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; -- 你会看到前两个的执行计划完全一样性能排序一般情况count(*)≈count(1)⭐⭐⭐⭐⭐count(主键列)⭐⭐⭐⭐count(非主键有索引列)⭐⭐⭐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(列名) -- 统计已完成订单数量假设 status2 是已完成 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个学生上课 ❗空座位不算七、总结与最佳实践最终建议统计总行数一律用count(*)这是 SQL 标准写法性能最优MySQL有专门优化语义最明确统计某列非 NULL 数量用count(列名)这是它的本职工作不要用它统计总行数关于count(1)性能与count(*)一样但不够标准像方言建议统一用count(*)性能关键点大表避免频繁 count考虑使用缓存或汇总表为 count(列名) 的列加索引一张图看懂count(*) - 总数 - 最快 - 推荐使用 ↓ count(1) - 总数 - 一样快 - 可用但不标准 ↓ count(主键) - 总数 - 次快 - 主键非NULL时可用 ↓ count(索引列) - 非NULL数 - 较慢 - 有索引时可用 ↓ count(普通列) - 非NULL数 - 最慢 - 谨慎使用
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2477907.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!