count的几种写法

孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说,“对呀对呀!……回字有四样写法,你知道么?”我愈不耐烦了,努着嘴走远。孔乙己刚用指甲蘸了酒,想在柜上写字,见我毫不热心,便又叹一口气,显出极惋惜的样子。

写下这个标题,立刻就联想到了孔乙己,于是找出了上文的引用。闲话不表,说正事。

count查询一般在统计满足某条件的数据总数时会用到,常见的就是数据统计分析和分页查询的场景。

这篇文章的目的主要是想研究一下count的用法,找到使用这个方法的最佳实践。

实现

查询引擎差异

总所周知,mysql是基于多种存储引擎的数据库,不同的存储引擎之间实现差异很大,在myisam引擎下,将总行数直接保存了下来,而innodb没有这样做。

之所以innodb不保存也很好理解,innodb有事务隔离,在不同的事务内,统计到的数据行数是可能存在差异的。

估算方法

统计行数的方法其实并不止这一种,show table status语句也能够查询到每张表的数据行数,差别在于,count方法得到的是精确值,而使用这种方法拿到的是一个估算的值,在官方文档的描述中提到,这种估算方法计算出来的值误差能达到50%,所以如果日常使用,只能提供对数据量级上的估算,在单表数据量大的时候也许有点用、

那么他又是怎么实现的呢?

数据库中存在描述表信息的元数据,mysql存放元数据的库叫information_schema,这个库下的TABLES表里有个字段叫TABLE_ROWS,用这个字段来保存估算的数据行数。

select TABLE_ROWS from information_schema.'TABLES' WHERE TABLE_NAME = 'xxxx'

使用查询验证了一下,两者的值一致,说明确实是取的这里的值

性能

先说结论,性能上

count(*) = count(1) >= count(primary key) >= count(非空字段) >= count(可空字段)

几种查询方式各自的实现:

语句实现
count(1)遍历整张表,不取值,累加行数
count(primaryKey)遍历整张表,把主键值拿出来,累加行数
count(非空字段)遍历整张表,读出这个字段,累加
count(可空字段)遍历整张表,读出这个字段,判断不为空后累加
count(*)遍历整张表,数据库层面进行了优化,不会把字段全部取出来,按行累加

阿里的java开发手册上将count(*)作为推荐用法,书里给出的理由:

【强制】不要使用 count(列名)或 count(常量)来替代 count(),count()是 SQL92 定义的标
准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。

验证

虽然根据资料得出了关于性能差异的结论,但是还是想自己找张表验证一下结论。
找了张6w数据的表尝试使用不同的count语句进行查询,发现性能差异并不明显,也许是数据量太小,反正在我的测试下几乎没有差异。

参考资料

https://segmentfault.com/a/1190000022262561

https://juejin.cn/post/6844903974445776903

https://www.zhihu.com/question/34781415

https://www.modb.pro/db/48242

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值