查询
1 | select ... from .... |
执行顺序:
1 | 1 from |
group by
MySql从5.7版本开始默认开启only_full_group_by
规则,规则核心原则如下,没有遵循原则的sql会被认为是不合法的sql
order by
后面的列必须是在select
后面存在的select
、having
或order by
后面存在的非聚合列必须全部在group by
中存在
count(*)、count(1)、count(主键)、count(字段)的区别
以下,基于 InnoDB
含义区别
count()是一个聚合函数,对于返回的结果集,会逐行判断,若返回的不是 NULL,就会加 1,否则不加。
因此,count(*)、count(主键 id)和count(1)都表示返回满足条件的结果集的总行数;而count(字段),则表示返回满足条件的数据行里面,参数“字段”不为 NULL 的总个数。
性能区别
分析性能,考虑以下几个原则:
- server 层要什么就会返回什么;
- InnoDB 只返回必要的值;
- 优化器只优化了count(*)
- 对于count(主键id),InnoDB 会遍历全表,取每行的主键 id,返回给 server 层,server 层拿到数据后,进行判断累加。
- 对于count(1),InnoDB 仍遍历全表,但是不取值,server 层对返回的每一行数据新增一个 1,然后进行判断累加;
因此,count(1)要更快些,因为无需取值。从引擎返回 id 会涉及到解析数据行,以及拷贝字段值的操作。 - 对于count(字段):
- 如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;
- 如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是null,还要把值取出来再判断一下,不是 null 才累加。
- 但是
count(*)
是例外,并不会把全部字段取出来,而是专门做了优化,不取值。count(*)
肯定不是null
,按行累加。
结论
按照效率排序的话
1 | count(字段) < count(主键 id) < count(1) ≈ count(*) |
所以我建议你,尽量使用count(*)