count对比
| count(1) | count(*) | count(非空列) | count(可以为空列) |
效率(innodb引擎) | 1 | 1(建议使用) | 2 | 3 |
是否会忽略null | 会 | 会 | 不会 | 不会 |
count(*)
- 会遍历全表,mysql优化后,该函数不会取值,也不会存在null,读行,累计计数返回;
- SQL92定义的标准统计行数的语法;
- MySQL 8.0.13开始,针对InnoDB的SELECT COUNT(*) FROM table语句,在扫表的过程中做了一些优化,注:这里的语句没有where和group by条件
- innodb中索引氛围聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是改行记录的主键的值,需通过主键回表获取整行记录,虽然查询中多了一道工序,但是相比来说非聚簇索引比聚簇索引小,MySQL会优先选择最小的非聚簇索引来扫描表
- 当业务中判断是否存在时,可以考虑改用select 1 from table limit 1,让数据库查询的时候遇到一条就返回,这样效率会有所提升
count(常数)
- 遍历全表,按行读取数据,每行计数为1,累加返回
- 关于count(1)和count(*):MySQL官方文档中注明:InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.,由此看来效率上没有什么很大的区别
count(非空列) --count(id)
- 遍历全表,按行读取数据(会选择最小索引树遍历,比相同情况下count字段效率更高),取每行主键id,判断该字段不可为空,累加计数,返回;
count(非空列) --count(普通非空列)
- 遍历全表,按行读取数据,取每行该字段,判断该字段不可为空,累加计数,返回;列上没有索引时,会遍历主键索引树
count(可为空列)
- 遍历全表,按行读取数据,取每行该字段,判断该字段是否为空,非空则累加计数,返回;
- 列上没有索引时,会遍历主键索引树
阿里巴巴开发规范count相关
- 【强制】不要使用count(列名)或count(常量)来替代count(*),count(*)是SQL92定义的标准统计行数的语法,和数据库无关,跟null和非null无关。
说明:count(*)会统计值为null的行,而count(列名)不会统计此列为null值的行 - 【强制】count(distinct col)计算该列除null之外的不重复行数,注意counr(dintinct col1,col2)如果其中一列全为null,那么即使另一列有不用的值,也返回为0.
- 【强制】当某一列的值全为null时,count(col)的返回结果为0,但sum(col)得返回结果为null,因此使用sum()时需注意NPE问题。
正解:可以使用如下方式来避免sum的NPE问题,select ifnull(sum(col),0) from table - 【强制】使用isnull()来判断是否为null值
说明:null与任何值的直接比较都为null
1)null<>null的返回结果是null,而不是false
2)null = null 的返回结果是null,而不是true
3)null <> 1的返回结果是null,而不是true
反例:在sql语句中,如果在null前换行,影响可读性。select * from table where col1 is null and col3 sos not null;而isnull(col)是一个整体,简洁易懂。从性能数据上分析,isnull(col)执行效率更快一些 - 【强制】代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。