暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

你清楚count(*),count(1),count(id)的区别吗?

SQLBABY 2021-04-29
2794

你清楚count(*),count(1),count(id)的区别吗?


在日常的SQL中,我们统计总量的时候经常会用到count,有些同学喜欢用count(*),还有些同学用count(1),甚至还有用count(id/字段),那么这些写法在执行过程和执行结果上有什么区别吗?今天就带大家解开这个谜底。


1:count函数的定义

我们看下mysql官方对count函数的定义。

这里包含三层意思:COUNT(expr)返回selsct检索语句中expr的值不为null的行数,其结果是一个BIGINT类型的值;如果没有匹配的行也就是所有行都是null或者表中没有数据,则返回0;但是需要注意的是如果使用的是count(*)则返回结果会包含null的记录,也就是说,即使这一行全为null也会统计的结果中。通过官方的定义我们不能发现,count就是对表中的行数进行计数,只不过根据count()括号里面的内容不同结果会稍有不同。


2:count函数的执行过程

结果会根据不同的条件有差异,那么其执行过程会有差异吗?


根据mysql执行引擎的不同,count的执行过程也会不同,我们以count(*)为例来分别介绍二者的执行原理。

  • MyISAM引擎:这个引擎最大的特点是不支持事务,锁的话是表级锁,正是由于是表级锁,针对表的操作都需要串联操作,不会出现两个或多个执行程序对一张表的同时操作,也就是说表的行数是稳定的,可维护的。针对count(*) 的操作,mysql自己了一个优化,类似于维护一份元数据信息,专门用来记录表的行数,这样每当有count(*)查询的时候就直接返回这个维护好的值,不需要再扫描全表了。所以它是一个O(1)复杂度的操作。

  • InnoDB引擎:支持事务支持行级锁,行级锁的特点是多个事务可以同时对一张表进行读写,只要是不同的行就行。但是这样一来表的行数就会变化很快而不可维护,mysql本身也就无法专门维护一个值去记录表的行数了。所以针对count(*)的操作不得不扫描全表以返回一个准确的结果。这是一个O(n)复杂度的操作。

优化:虽然在InnoDB引擎下没有一个直接返回的结果,但是随着mysql版本的不断升级,官方还是做了许多优化的,主要是索引上的优化。从上面我们知道在这个引擎下不可避免的要扫描全表,所以我们也只能再扫描全面上下功夫。由于count(*)不关心具体的列,所以在扫描的过程中我们如果可以选择一个较低成本的索引的话就可以节省扫描的时间。在InnoDB中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。这种情况下是非聚簇索引要比聚簇索引小得多,所以在具体执行的过程如果有非聚簇索引的活mysql会自动选择在非聚簇索引的列上做统计,这样就能提高查询的速度。

备注:以上都是在SQL语句中没有where和group by等限定条件下的查询分析。


3:count(*)和count(1)的对比

首先这两者的执行结果是完全一致的,也可以把count(1)换成其他的数字如count(8)甚至是字符串如count(‘x’),都不会影响执行的结果。但是针对二者的执行过程,网上是众说纷纭,一种主流的观点是count(*)比count(1)快,原因是mysql针对 count( *)这种操作做了特殊的优化;另外一种声音是count(1)比count(*)快,因为count(*)在执行过程中会先转为为count(1)然后在执行,直接count(1)的话少了一步转换操作,自然会快一些。那么哪种说更有道理呢?我们还是来看官方的说明:

  • 意思就是说对于InnoDB引擎来说count(*)和count(1)的底层操作是一致,在优化上是一致的,没有差异。所以结论就是二者的执行速度是一眼的,不存在孰优孰劣的差异。


  • 不过对于MyISAM引擎来说,只有第一列的值全部不为null的时候,count(1)才和count(*)拥有相同的执行优化。

由于我们通常查询的时候并不关心底层引擎使用的MyISAM还是InnoDB,而且不论那种引擎count(*)都是最优的操作,并且这种写话还是SQL_92标准语法推荐的操作,所以推荐大家使用count(*)来取代其他的操作。

看完执行结果相同的count(*)和count(1)的对比,我们再来看下count(key)主键和count(other)其他列的对比差异。首先不论是count(主键)还是count(其他列)都是需要扫描全表取出每一条记录的,但是count(其他列)的时候还需要判断取出的值是否为null,不为null的时候才进行统计,而对于count(主键)来说,主键是不会为null的,所以会少了一步判断,性能上会更优一些。

以上就是count函数执行过程的分析与对比。


3:count执行结果的对比

我们以一张excel表格中的数据为例来说明不同count()的执行结果。

  • count(*)=5--统计全部的记录行数,包括为null的行

  • count(id)=5--按照主键统计所以行数,扫描全表统计

  • count(1)=5--统计全部的记录行数,包括为bull的行

  • count(name)=5--按照name列统计name不为null的记录行数

  • count(age)=3--按照age列统计age值不为null的记录行数

  • count(address)=3--按照address统计address不为null的记录行数

大家根据上面的介绍count会排除值为null的记录以及我们表格中的数据不难得出上面的执行结果,所以这里不在详细介绍了。


4:总结

  1. 执行速度上:针对一般情况(SQL语句中没有where条件)执行速度上

    count(*)=count(1)>count(主键)>count(其他列),在没有其他特殊要求的情况下推荐大家使用count(*)来代替其他的count。

  2. 执行结果上,count(*)与count(1)以及count(主键)的结果完全相同,即返回表中的所有行数,包含null值;count(其他列)会排除掉该列值为null的记录,返回的值小于或者等于总行数。

  3. 学习方法上:不要轻易相信网上的结果,有矛盾和疑惑的情况到官网上去查看官方的说明才是正确可靠的做法。如果可能的话,自己最好实践一遍,实践才能出真知。





END



数据库
文章转载自 SQLBABY,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

玻璃钢生产厂家临高县商场美陈天津广场玻璃钢雕塑价格杭州玻璃钢卡通雕塑优惠大连玻璃钢雕塑样式优雅建邺玻璃钢花盆花器现代玻璃钢雕塑要求玻璃钢鹿雕塑厂家报价虹口区拉丝玻璃钢雕塑服务介绍福州多彩玻璃钢雕塑多少钱江苏大型商场美陈采购河西商场户外美陈江门市玻璃钢雕塑设计建材商场美陈江门美陈玻璃钢动物雕塑主题公园玻璃钢卡通形象雕塑泡沫玻璃钢雕塑哪家专业武汉中山玻璃钢雕塑杭州玻璃钢花盆供应玻璃钢小兔子雕塑赣州户外玻璃钢雕塑销售电话玻璃钢瓜果雕塑厂家电话洛阳玻璃钢卡通雕塑厂家地址深圳批发玻璃钢雕塑供应厂家正宗玻璃钢雕塑厂家销售电话玻璃钢雕塑维修方法玻璃钢雕塑哪里买好点半边地球仪玻璃钢雕塑品牌玻璃钢雕塑批发市场山西户外玻璃钢雕塑价位玻璃钢人像雕塑专业平台香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化