MySQL的COUNT(*)和COUNT(1)

之前虽然知道COUNT(*)和COUNT(1)都能用来统计行数,但是一直以为COUNT(1)中的1是指第一列,然后也没多想,昨天看到了代码里有个地方写着COUNT(0),代码还运行的非常好,惊到我了。然后查了下,发现是我太辣鸡了。
Snipaste_2020-03-24_18-00-49.png

References

首先,SELECT 1 FROM table会将表中的每一行都返回常量1,像这样的:

mysql> select 1 from language;
+---+
| 1 |
+---+
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
| 1 |
+---+
6 rows in set (0.00 sec)

一般用来简单检测WHERE子句或者JOIN之类的SQL写的对不对(感觉这样用的人也不多)。
COUNT(*)会统计所有行数,COUNT(expression)会统计符合表达式的非null值,COUNT(column_name)会统计对应列中非null值。
由于0和1都是非null值,所以COUNT(0) = COUNT(1),并且和COUNT(*)统计的行数相同。虽然概念不同,但是结果一样。
那么根据MySQL的文档:

COUNT(*) is somewhat different in that it returns a count of the number of rows retrieved, whether or not they contain NULL values.

InnoDB does not keep an internal count of rows in a table because concurrent transactions might “see” different numbers of rows at the same time. Consequently, SELECT COUNT(*) statements only count rows visible to the current transaction.

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.

For MyISAM tables, COUNT(*) is optimized to return very quickly if the SELECT retrieves from one table, no other columns are retrieved, and there is no WHERE clause.
For example:

mysql> SELECT COUNT(*) FROM student;

This optimization only applies to MyISAM tables, because an exact row count is stored for this storage engine and can be accessed very quickly. COUNT(1) is only subject to the same optimization if the first column is defined as NOT NULL.
由于原文比较多,这里节选了一部分。
可以看出来COUNT(*)返回所有查询到的行,无论是否包含NULL值(这里我测试了下,即使表只有1列,并且为NULL,也可以准确统计行数)。并且InnoDB由于并发事务无法准确的单独保存行数来提高COUNT(*)的性能。所以只会统计当前事务可见的行数。
InnoDB以相同的方式处理SELECT COUNT(*)SELECT COUNT(1),没有性能区别。
对于MyISAM表格,如果SELECT查一个表的行数,没有同时查询其他的列,没有WHERE子句,那么COUNT(*)被优化很快返回,这是由于MyISAM的表单独保存了行数。

因此对于一般的InnoDB来说,除了COUNT(column_name)会统计NULL值外,其他都差不多,怎么使用其实看喜好就可以了。

标签: none

添加新评论

ali-01.gifali-58.gifali-09.gifali-23.gifali-04.gifali-46.gifali-57.gifali-22.gifali-38.gifali-13.gifali-10.gifali-34.gifali-06.gifali-37.gifali-42.gifali-35.gifali-12.gifali-30.gifali-16.gifali-54.gifali-55.gifali-59.gif

加载中……