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

GLM技术复盘:篇论文深度解读智谱模型家族

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;

-- 你会看到:前两个的执行计划完全一样!

性能排序(一般情况):

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(列名)

-- 统计已完成订单数量(假设 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个学生上课" ?(空座位不算)

七、总结与最佳实践

最终建议

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

这是 SQL 标准写法

性能最优(MySQL有专门优化)

语义最明确

统计某列非 NULL 数量,用 count(列名)

这是它的本职工作

不要用它统计总行数

关于 count(1)

性能与 count(*) 一样

但不够"标准",像方言

建议统一用 count(*)

性能关键点

大表避免频繁 count

考虑使用缓存或汇总表

为 count(列名) 的列加索引

一张图看懂

count(*) -> 总数 -> 最快 -> 推荐使用

count(1) -> 总数 -> 一样快 -> 可用但不标准

count(主键) -> 总数 -> 次快 -> 主键非NULL时可用

count(索引列) -> 非NULL数 -> 较慢 -> 有索引时可用

count(普通列) -> 非NULL数 -> 最慢 -> 谨慎使用

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

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

相关文章:

  • 2026成都奔驰威霆配置可靠服务商推荐榜 - 优质品牌商家
  • 一篇讲透线程池核心代码:从 submit 到执行链路(含 lambda / move / packaged_task)
  • 告别卡顿!用z-paging虚拟列表优化Uni-app长列表,Tab切换丝滑回顶方案
  • AI CRM公司排名前瞻:原圈科技如何颠覆高净值行业获客
  • 第06章:LangChain使用之Tools
  • [实战]C语言实现带限高斯白噪声生成与Python频谱验证(附完整代码)
  • 在快马平台一键生成mac版openclaw数据抓取脚本原型
  • 为什么现代C++项目都推荐CMake+Ninja?实测构建速度对比Makefile
  • 超低功耗血压计和心率监视系统(C语言实现)
  • 树莓派入门实战:从烧录系统到远程连接全流程指南
  • 终极视频下载解决方案:如何利用Video DownloadHelper伴侣应用轻松获取在线资源
  • 避坑指南:用Python+Selenium批量爬取专利数据时,你可能遇到的5个坑及解决办法
  • 通达信手机版安装自定义指标保姆级教程:以‘双紫擒龙’为例,解决‘我的指标’不显示问题
  • SDE | 概率论基础2
  • 暗黑3终极自动化助手:5分钟配置智能战斗宏,彻底告别手酸烦恼
  • 阿里云物联网平台OTA升级避坑指南:从版本号上报到Bin文件拉取的全流程排错
  • dSPACE ControlDesk实战指南:从仪表板布局到总线信号实时监测
  • GEO和SEO有什么区别?一文看懂两代“流量入口”的分水岭
  • 零基础鸿蒙应用开发第二十二节:类的继承与多态入门
  • Monaco Editor 与 CodeMirror 深度对比:从语言支持到实际应用场景
  • A100 vs H20,谁才是DeepSeek-R1私有化的性价比之选?一份2025年的硬件选型与成本精算报告
  • 让ai成为你的命令行导师,快马平台智能解读与生成openclaw命令
  • Cesium性能优化:你可能不知道的onTick事件监听器内存泄漏问题
  • 深入解析Cache替换算法与写策略:性能优化实战指南
  • 家用除螨仪有线还是无线除螨效果好?除螨仪哪个牌子最专业?汇总揭秘除螨仪10大品牌排行
  • 2026储能电池靠谱品牌推荐榜:光伏控制器/太阳能控制器/磷酸铁锂电池/逆变器/锂电池/储能电池/储能电源/选择指南 - 优质品牌商家
  • 实战应用:基于快马平台开发小龙虾食品安全溯源H5页面,增强消费信任
  • 3个技巧解锁Inter字体潜能:专业排版必备的OpenType特性详解
  • 关于统好 AI可持续发展三大趋势
  • 2026长沙GEO优化公司权威实测:基于稳定性与转化效率的TOP5服务商深度推荐