zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    hiho#1445 重复旋律5 求子串数量 后缀自动机
    SPOJ LCS2 后缀自动机
    SPOJ-LCS 后缀自动机
    bzoj 3261 最大异或和 可持久化字典树(01树)
    【洛谷1297】单选错位
    【HAOI2008】木棍分割
    【SDOI2016】排列计数
    【HAOI2008】下落的圆盘
    【HAOI2008】硬币购物
    【洛谷5520】青原樱
  • 原文地址:https://www.cnblogs.com/sansui/p/12495764.html
Copyright © 2011-2022 走看看