跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
SQL

MySQL 中 COUNT(*) 与 COUNT(1) 的区别及性能对比

综述由AI生成探讨了 MySQL 中 COUNT(*) 与 COUNT(1) 的区别。在现代 MySQL 版本(5.7+)中,两者执行计划相同,性能无差异,均统计所有行包括 NULL 值。而 COUNT(列名) 会忽略 NULL 值。最佳实践推荐使用 COUNT(*) 统计总行数,因其语义更直观且团队统一性更好。无需再纠结于旧版本的性能差异说法。

无尘发布于 2026/3/27更新于 2026/5/3036 浏览

概述

在 SQL 查询中,COUNT 函数是最常用的聚合函数之一,用于统计行数。然而,很多开发者会对 COUNT(*) 和 COUNT(1) 的区别感到困惑,甚至在一些老教程中还能看到'COUNT(1) 比 COUNT(*) 更快'的说法。本文将深入探讨这两者的本质、性能差异以及正确的使用场景。


一、基本概念

COUNT(*)

COUNT(*) 统计表中的所有行数,包括值为 NULL 的行。这里的星号并不代表'所有列',而是一个特殊的语法,表示'整个行'。

COUNT(1)

COUNT(1) 统计表达式 1 不为 NULL 的行数。由于常量 1 永远不为 NULL,所以它同样会统计表中的所有行,结果与 COUNT(*) 完全一致。

示例:
假设有一张用户表 users,包含 3 行数据,其中一行的 email 字段为 NULL:

SELECT COUNT(*) FROM users; -- 返回 3
SELECT COUNT(1) FROM users; -- 返回 3
SELECT COUNT(email) FROM users; -- 返回 2(忽略 NULL)

二、性能对比:现代 MySQL 中无差异

在 MySQL 5.7 及更高版本中,优化器会将 COUNT(1) 自动重写为 COUNT(*),因此两者的执行计划完全相同。我们可以通过 EXPLAIN 来验证:

EXPLAIN SELECT COUNT(*) FROM users;
EXPLAIN SELECT COUNT(1) FROM users;

两者的输出结果(如 id、select_type、Extra 等字段)没有任何区别。这意味着它们在性能上是完全等价的,不存在谁比谁快的问题。

为什么早期会有'COUNT(1) 更快'的说法?

在非常古老的 MySQL 版本(如 3.23)中,COUNT(*) 的实现方式可能涉及读取所有列,而 COUNT(1) 只需读取常量,因此确有性能差异。但这个时代早已结束,现代优化器对 COUNT(*) 做了专门优化,它会选择最优的索引(通常是二级索引)来统计行数,而不是全表扫描。


三、关键区别:COUNT(列名) 与 COUNT(*)/COUNT(1)

真正需要区分的是 COUNT(列名) 与 COUNT(*)/COUNT(1),它们的行为有本质差异:

函数统计对象是否包含 NULL
COUNT(*)所有行是
COUNT(1)所有行(因为 1 非 NULL)是
COUNT(列名)该列非 NULL 的行否

示例验证:

-- 创建测试表
CREATE TABLE t (id INT, name VARCHAR(10));
INSERT INTO t VALUES (1, 'Alice'), (2, NULL), (NULL, 'Bob');
SELECT COUNT(*) FROM t; -- 3
SELECT COUNT(1) FROM t; -- 3
SELECT COUNT(id) FROM t; -- 2(id 为 NULL 的行被忽略)
SELECT COUNT(name) FROM t; -- 2(name 为 NULL 的行被忽略)

四、存储引擎的影响

不同的存储引擎对 COUNT 的处理略有不同,但这并不影响 COUNT(*) 与 COUNT(1) 的等价性。

  • MyISAM:会缓存表的总行数,因此不带 WHERE 条件的 COUNT(*) 极快,直接返回缓存值。COUNT(1) 同样利用缓存,两者速度一致。
  • InnoDB:由于支持 MVCC(多版本并发控制),不同事务看到的数据版本可能不同,因此无法缓存总行数。每次 COUNT(*) 都需要实时统计,优化器会优先选择扫描最小的二级索引来减少 IO。同样,COUNT(1) 也采用相同的优化策略。

五、最佳实践建议

  1. 统计总行数:推荐使用 COUNT(*),因为它最直观地表达了'统计所有行'的意图,且没有性能损失。
  2. 统计非 NULL 值的行数:使用 COUNT(列名)。
  3. 带条件统计:一律使用 COUNT(*) 配合 WHERE 子句,如 SELECT COUNT(*) FROM table WHERE status=1;。
  4. 代码一致性:团队内统一使用 COUNT(*),避免混用 COUNT(1) 引起不必要的困惑。

六、结论

在当今的 MySQL 版本中,COUNT(*) 和 COUNT(1) 没有任何区别——无论是语义还是性能。它们都统计所有行,执行计划相同,运行速度相同。开发者无需再纠结选择哪一个,只需记住与 COUNT(列名) 区分即可。

如果你还看到有人争论'COUNT(1) 比 COUNT(*) 快',可以友善地告诉他:那是上个世纪的故事了。😄


延伸阅读:

  • MySQL 官方文档:COUNT 函数
  • MySQL 优化器如何处理 COUNT

目录

  1. 概述
  2. 一、基本概念
  3. COUNT(*)
  4. COUNT(1)
  5. 二、性能对比:现代 MySQL 中无差异
  6. 为什么早期会有“COUNT(1) 更快”的说法?
  7. 三、关键区别:COUNT(列名) 与 COUNT(*)/COUNT(1)
  8. 四、存储引擎的影响
  9. 五、最佳实践建议
  10. 六、结论
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • FPGA:重构硬件逻辑的柔性算力核心,国产替代的破局关键
  • 普通产品经理转型 AI 产品经理的准备指南
  • Python+AI 零基础变现指南:3 天开发职场文案 App 实战
  • 前端面试题 JavaScript 核心知识点详解
  • 开源大模型选型指南:如何构建合适的技术底座
  • OpenClaw 接入自定义模型并通过 WebUI 完成智能操作
  • WebLogic MIB 与 AdventNet MIB Browser 工具使用指南
  • 基于 Open-AutoGLM 的手机自动化部署与实战指南
  • Spring Boot 事件机制详解:原理与示例
  • OpenClaw 生态:16 款 AI Agent 选型指南
  • 从零实现Vivado下载与初始设置:FPGA开发第一步
  • 基于FPGA的微波炉控制器设计
  • AI 写作辅助平台评测:炼字工坊与蛙蛙写作
  • 六自由度机器人逆运动学解析与 MATLAB 实现
  • VSCode 接入智谱 GLM-4 及自定义大模型配置方案
  • VR 音游音符轨道系统开发实录与原理解析
  • Java 常见集合框架详解
  • Python 数据分析与 Spark、Hive 对比
  • 哈希表核心实现:开放定址法与链地址法详解
  • 如何成为一名成功的 AI 产品经理:从传统产品到 AI 产品的进阶之路

相关免费在线工具

  • SQL 美化和格式化

    在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。 在线工具,SQL 美化和格式化在线工具,online

  • SQL转CSV/JSON/XML

    解析 INSERT 等受限 SQL,导出为 CSV、JSON、XML、YAML、HTML 表格(见页内语法说明)。 在线工具,SQL转CSV/JSON/XML在线工具,online

  • CSV 工具包

    CSV 与 JSON/XML/HTML/TSV/SQL 等互转,单页多 Tab。 在线工具,CSV 工具包在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online