count(1),count(*),count(主键) 性能对比

前言

前段时间关于统计数量的sql问题和朋友进行了讨论,网上关于这三种查询方式说法不一,主要有以下两种说法。

  1. count(*) = count(主键) > count(1)
  2. count(主键) > count(*) > count(1)

今天对这三种方式进行探究。

数据库为mysql 5.7.12,引擎为InnoDB。

建表

  1. CREATE TABLE `user` (

  2.  

    `id` int(32) NOT NULL AUTO_INCREMENT,

  3.  

    `name` varchar(500) DEFAULT NULL COMMENT ‘姓名‘,

  4.  

    `deleted` int(2) NOT NULL DEFAULT ‘1‘ COMMENT ‘逻辑删除‘,

  5.  

    `created_date` datetime DEFAULT NULL COMMENT ‘创建时间‘,

  6.  

    `created_by` varchar(255) DEFAULT NULL,

  7.  

    `update_date` datetime DEFAULT NULL,

  8.  

    `update_by` varchar(255) DEFAULT NULL,

  9.  

    `version` int(11) NOT NULL DEFAULT ‘1‘ COMMENT ‘乐观锁‘,

  10.  

    PRIMARY KEY (`id`) USING BTREE

  11.  

    ) ENGINE=InnoDB AUTO_INCREMENT=1502726 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT=‘用户表‘;

循环插入150万条数据。

  1. DROP PROCEDURE
  2. IF
  3. EXISTS proc_initData;
  4. DELIMITER $
  5. CREATE PROCEDURE proc_initData () BEGIN
  6. DECLARE
  7. i INT DEFAULT 1;
  8. WHILE
  9. i <= 5000000 DO
  10. INSERT INTO user ( name, created_date, update_date )
  11. VALUES
  12. ( ‘哈哈哈啊哈哈哈‘, NOW(), NOW() );
  13. SET i = i + 1;
  14. END WHILE;
  15. END $ CALL proc_initData ();

这里需要使用到mysql的explain关键字,对count(1),count(*),count(id),count(name)分别查看性能

  1. explain select count(1) from user
  2. explain select count(*) from user
  3. explain select count(id) from user
  4. explain select count(name) from user

可以看出,select count(1)、count(*)、count(id)的执行计划是一毛一样的。多次执行取平均值,三者的性能也是非常趋近,因此可以认为三者性能相同。这里我加了个count(name)进行对比,并将最后30万条数据的name置空,可以看出性能有明显的差别。

mysql底层对count查询做了优化,当mysql确定count中的列名不为空时,实际上就是在统计行数。那么mysql内部会将count(列名)优化为count(*) —— 出自《高性能MySQL》一书

也就是说count(1)和count(主键字段)还是要优化到count(*)的,而如果只是统计某个列,只要该列不为空,无论是否为索引,都会被优化为count(*),因此三者性能并无任何差异。官方文档对其也进行了解释。

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

https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count

至此,事实上并未解决关于这个问题的疑惑。上面的内容都在强调“Mysql”,就是说,上面的验证可能仅对MySql有效,其他的数据库可能未必会对count语句进行优化。因此我又通过SQLServer去验证。

因为我本地并没有安装SQLServer,因此我是直接使用公司的开发库进行验证,这里不方便截图,直接说明一下200万条数据验证结果。

  1. 列名为主键,count(列名)会比count(1)快
  2. 列名不为主键,count(1)会比count(列名)快
  3. 如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(*)
  4. 如果有主键,则 select count(主键)的执行效率是最优的
  5. 如果表只有一个字段,则 select count(*)最优。

可见,在SQLServer中,count(*)的性能并没有count(主键)高。

结语

根据上面对两个数据库的验证得出结论:不说是什么数据库都是耍流氓!SQL标准只提供了count这个内置函数,所有的数据库需要遵循这个标准,但是不同的数据库对于count的处理不同。在mysql中建议写count(*),而在SQLServer中建议写count(主键),在PostgreSql以及其他数据库中并未对其进行验证

文章原文:https://blog.csdn.net/qq_36403693/article/details/103758765

原文地址:https://www.cnblogs.com/sansui/p/12495764.html

时间: 2024-10-04 12:54:06

count(1),count(*),count(主键) 性能对比的相关文章

MySql中测试GUID 与Int自增主键 性能对比 总结适用场景【转】

一. 创建以下三个数据表: int 主键自增表, guid主键表, 关联以上两个表的关系表tbl_test_relation CREATE TABLE `tbl_test_int` (    `id` INT(11) NOT NULL AUTO_INCREMENT,    `name` VARCHAR(50) NULL DEFAULT NULL,    `comment` VARCHAR(100) NULL DEFAULT NULL,    PRIMARY KEY (`id`))COMMENT=

count(*),count(1)和count(主键)的区别

如果null参与聚集运算,则除count(*)之外其它聚集函数都忽略null.如: ID     DD 1      e 2    null select  count(*) from table  --结果是2 select  count(DD)  from table  ---结果是1 效率问题: 当表的数据量大些时,对表作分析之后,使用count(1)还要比使用count(*)用时多了! 从执行计划来看,count(1)和count(*)的效果是一样的. 但是在表做过分析之后,count(

mysql主键uuid、uuid_short和int自增对比

数据库主键性能对比: 名称 存储长度 生成方式 1. uuid 32+4 uuid()函数 2. uuid20 20 UUID_SHORT()函数 3. bigint自增 20 auto_increment 测试表:id_int(). -- uuid测试表 CREATE TABLE `id_uuid` ( `id` varchar(50) NOT NULL, `name` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB

论证-select count(*)和select count(1)的区别

前言:今天看到同事转载的一篇<select count(*)和select count(1)的区别>的博文,兴致所致,就像对文中提出的结论进行验证一下: 从内容来看,主要是有主键和没有主键的影响,那么 第一步:创建test1(有主键),test2(无主键)两张表 CREATE TABLE `test1` ( `id` int(12) NOT NULL AUTO_INCREMENT, `value` int(12) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=In

count(*)、count(1)和count(column)区别以及执行效率高低比较

[mysql]count(*).count(1)和count(column)区别 小结:  count(*) 对行的数目进行计算,包含NULL.  count(column) 对特定的列的值具有的行数进行计算,不包含NULL值.  count(1) 这个用法和count(*)的结果是一样的. 性能问题:  1.任何情况下 SELECT COUNT(*) FROM tablename 是最优选择:  2.尽量减少 SELECT COUNT(*) FROM tablename WHERE COL =

COUNT(1)和COUNT(*)区别

项目经常用到count(1),但是和count(*)什么区别? 从下面实验结果来看,Count (*)和Count(1)查询结果是一样的,都包括对NULL的统计,而count(列名) 是不包括NULL的统计. 图1: 图2: PS: 如果表没有主键,count(1)比count(*)快. 如果有主键的话,主键作为count的条件时候count(主键)最快. 如果表只有一个字段的话那count(*)就是最快的. 如果使用count(*)多的话,建议使用指定列建立索引.

mysql中的count(primary_key)、count(1)、count(*)的区别

表结构如下: mysql> show create table user\G; *************************** 1. row *************************** Table: user Create Table: CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `pwd` varchar(50) NOT N

count(1)与count(*)比较:

如果你的数据表没有主键,那么count(1)比count(*)快 如果有主键的话,那主键(联合主键)作为count的条件也比count(*)要快 如果你的表只有一个字段的话那count(*)就是最快的啦 count(*) count(1) 两者比较.主要还是要count(1)所相对应的数据字段. 如果count(1)是聚索引,id,那肯定是count(1)快.但是差的很小的. 因为count(*),自动会优化指定到那一个字段.所以没必要去count(?),用count(*),sql会帮你完成优化

MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)

测试缘由 一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了拿实际的案例来说服他,所以准备做一个详细的测试.   作为互联网公司,一定有用户表,而且用户表UC_USER基本会有百万记录,所以在这个表基础上准测试数据来进行测试.            测试过程是目前我想到的多方位的常用的几种类型的sql进行测试,当然可能不太完善,欢迎大家留言提出更加完善的测试方