重新认识MySQL中的COUNT语句 (2)

我们知道,COUNT()的目的只是为了统计总行数,所以,他根本不关心自己查到的具体值,他如果能够在扫表的过程中,选择一个成本较低的索引进行的话,那就可以大大节省时间。

我们知道,InnoDB中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。

所以,相比之下,非聚簇索引要比聚簇索引小很多,所以MySQL会优先选择最小的非聚簇索引来扫表。

当我们建表的时候,除了主键索引以外,创建一个非主键索引还是有必要的。

至此,我们介绍完了MySQL数据库对于COUNT()的优化,这些优化的前提都是查询语句中不包含WHERE以及GROUP BY条件。

COUNT()和COUNT(1)

介绍完了COUNT(),接下来看看COUNT(1),对于,这二者到底有没有区别,网上的说法众说纷纭。

有的说COUNT()执行时会转换成COUNT(1),所以COUNT(1)少了转换步骤,所以更快。

还有的说,因为MySQL针对COUNT()做了特殊优化,所以COUNT()更快。

那么,到底哪种说法是对的呢?

看下MySQL官方文档是怎么说的:

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

画重点:

same way , no performance difference。

所以,对于COUNT(1)和COUNT(),MySQL的优化是完全一样的,根本不存在谁比谁快!

那既然COUNT()和COUNT(1)一样,建议用哪个呢?

建议使用COUNT()!

因为这个是SQL92定义的标准统计行数的语法,而且本文只是基于MySQL做了分析,关于Oracle中的这个问题,也是众说纷纭的呢。

COUNT(字段)

最后,就是我们一直还没提到的COUNT(字段),他的查询就比较简单粗暴了,就是进行全表扫描,然后判断指定字段的值是不是为NULL,不为NULL则累加。相比COUNT(),COUNT(字段)多了一个步骤就是判断所查询的字段是否为NULL,所以他的性能要比COUNT()慢。

总结

本文介绍了COUNT函数的用法,主要用于统计表行数。

主要用法有COUNT()、COUNT(字段)和COUNT(1)。

因为COUNT()是SQL92定义的标准统计行数的语法,所以MySQL对他进行了很多优化,MyISAM中会直接把表的总行数单独记录下来供COUNT()查询,而InnoDB则会在扫表的时候选择最小的索引来降低成本。当然,这些优化的前提都是没有进行where和group的条件查询。

在InnoDB中COUNT()和COUNT(1)实现上没有区别,而且效率一样,但是COUNT(字段)需要进行字段的非NULL判断,所以效率会低一些。

因为COUNT()是SQL92定义的标准统计行数的语法,并且效率高,所以请直接使用COUNT()查询表的行数!*

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgyspx.html