返回
揭秘:count(*)性能最差的谎言
后端
2023-10-05 03:47:56
从进入数据库行业以来,我就一直认为count(*)是效率最差的SQL查询,因为认知上 selete * from t
会读取所有表中的字段,所以凡事带有 *
字符的就觉得会读取表中所有的字段,当时网上有很多博客也这么说。
后来在实际工作中发现,很多时候count(*)的性能都比我想象的要好,甚至在某些情况下比其他聚合函数的性能还要好。
带着这个疑惑,我开始深入研究count()的底层原理和执行过程,最终揭开了count()性能最差的谎言。
count(*)的底层原理
count()的底层实现是通过扫描表中的所有行,然后对每一行进行计数。当表中没有数据时,count()的返回值为0。当表中只有一行数据时,count()的返回值为1。当表中有N行数据时,count()的返回值为N。
count(*)的执行过程
count(*)的执行过程可以分为以下几个步骤:
- MySQL查询优化器解析SQL语句,并将count(*)解析为一个聚合函数。
- MySQL查询优化器确定count(*)的聚合范围,即哪些行需要被计数。
- MySQL查询优化器生成执行计划,并选择一个最优的执行计划。
- MySQL执行引擎根据执行计划,扫描表中的所有行,并对每一行进行计数。
- MySQL执行引擎将计数结果返回给MySQL查询优化器。
- MySQL查询优化器将计数结果返回给客户端。
count(*)的性能表现
count(*)的性能表现与以下几个因素有关:
- 表的大小:表越大,count(*)的性能就越差。
- 索引的使用:如果表上存在索引,并且count()的聚合范围在索引范围内,那么count()的性能就会很好。
- 聚合函数的使用:如果count()与其他聚合函数一起使用,那么count()的性能就会受到其他聚合函数的影响。
- 硬件资源:服务器的CPU、内存等硬件资源也会影响count(*)的性能。
如何优化count(*)查询
以下是一些优化count(*)查询的技巧:
- 使用索引:如果表上存在索引,并且count()的聚合范围在索引范围内,那么可以使用索引来优化count()查询。
- 使用分区表:如果表非常大,可以将表分成多个分区表,然后对每个分区表分别执行count(*)查询。
- 使用物化视图:如果count()查询的聚合范围经常不变,那么可以创建一个物化视图来存储count()的查询结果。
- 使用延迟物化视图:如果count()查询的聚合范围经常变化,那么可以使用延迟物化视图来优化count()查询。
总结
count()的性能并不总是最差的。在某些情况下,count()的性能甚至比其他聚合函数的性能还要好。因此,在优化SQL查询时,不应该一味地认为count(*)的性能最差,而应该根据具体的查询场景来选择最优的聚合函数。