原文链接:www.gbase.cn/community/p…
更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。
在 GBase 8c 数据库的日常开发与运维中,count 函数是使用频率最高的函数之一,作用是统计表中符合查询条件的记录行数。无论是业务数据统计、接口分页查询,还是数据校验场景,几乎都离不开它。
但在实际开发中,count(*)、count(1)与 count(column_name)这三种写法常常被混用,不少开发者存在如下误区:要么认为三者是等价的,可以随意替换;要么纠结于哪种写法性能更优,反而忽视了它们的核心差异。本文结合 GBase 8c 数据库的特性,通过具体示例,详细分下下三者的相同点与区别。
- 从功能上看,三者都是用于统计记录数量,且返回结果均为 bigint 类型,这是聚合函数 count()决定的。
- 从使用场景来看,三者都可以与 where 过滤条件、group by 分组子句、having 筛选子句配合使用,实现精准的分组统计需求。比如统计某一班级的学生人数、某一时间段的订单数量,三者均可配合 where 条件实现。
- 在无 where 过滤条件、且表中指定列无 null 值的前提下,三者的统计结果一致。下面通过 gbase 环境下的示例,来说明下这一特性。
首先创建测试表并插入无 null 值的测试数据:
create table student(id int primary key, name varchar(50), age int);
insert into student values(1, 'aaa', 20), (2, 'bbb', 21), (3, 'ccc', 22);
分别执行以下三条查询语句,最终返回结果均为 3,与表中实际记录数一致:
select count(*) from student; 直接统计所有记录行数,不区分列值。
select count(1) from student; 用常量 1 指代每条记录,判断记录存在并计数。
select count(id) from student; 统计 id 列非空的记录数,结果与前两者一致
上面是共性,下面了解下三者的差异,这也是日常开发中最易踩坑的地方,主要集中在 null 值处理、统计逻辑、可读性及性能表现四个方面,其中 null 值处理是最重要的区别。
-
第一个差异:null 值处理逻辑不同。count(* )的逻辑是“统计所有记录存在性”,无论表中任意列是否为 null,哪怕一条记录的所有列值都为 null,也会被计入统计;count(1)与 count(*)的 null 值处理逻辑是一样的,它不关注表中任何列的内容,仅通过常量 1 判断记录是否存在,只要记录存在,就会计数,不受任何列 null 值的影响。
而 count(column_name)时不同的,它只统计指定列中值不为 null 的记录,若该列存在 null 值,会自动忽略这些 null 值,不纳入统计范围。我们插入一条含 null 值的记录,来验证这一差异:insert into student values(4, null, null);再次执行三条查询语句,结果出现明显差别:count(*)和 count(1)的结果均为 4,count(name)和 count(age)的结果为 3,count(id)的结果仍为 4。这一例子说明,count(column_name)的统计结果受指定列 null 值的直接影响。
-
第二个差异:统计逻辑与可读性不同。count(*)是 SQL 标准写法,语义最清晰,表示“统计表中所有记录行数”,无论表结构如何变化,其统计逻辑都不会改变,GBase 8c 也对其做了专门优化,可读性和通用性最优。count(1)属于扩展语法,等价于“判断每条记录是否存在,存在则计数”,可读性略差。count(column_name)的语义是“统计指定列的非 null 值数量”,并非单纯统计行数,需结合具体业务场景使用,比如统计有有效姓名的学生数量、有手机号的用户数量,针对性强。
-
第三个差异:性能表现略有不同。在 GBase 8c 中,count(*)和 count(1)的性能基本一致,数据库优化器会自动将两者转换为相同的执行计划,无需扫描全表,效率极高。
而 count(column_name)的性能取决于该列是否有索引:若指定列建立了索引,数据库会通过索引扫描快速过滤 null 值,效率较高;若该列无索引,数据库需要进行全表扫描,并逐行判断列值是否为 null,效率远低于前两者,且数据量越大,性能差异越明显。
使用建议:统计表中记录行数时,优先使用 count(*),适配所有表结构;count(1)可作为替代方案,但不推荐用于追求代码可读性的场景;当需要统计指定列的非 null 值数量时,才使用 count(column_name),且尽量给该列建立索引,以优化查询性能。
综上,count(*)、count(1)与 count(column_name)并非完全等价,差异集中在 null 值处理和统计逻辑上。掌握它们的异同,结合 GBase 8c 的性能特性选择合适的写法,既能有效提升 SQL 查询效率,也能增强代码可读性,规避因误用导致的统计误差,让数据统计更精准、高效。
原文链接:www.gbase.cn/community/p…
更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。