网站做301根目录在哪里,Dw制作个人网站,四川建设人才培训网站,近三天新闻50字左右文章目录 前言COUNT(exper)COUNT(*)优化COUNT(*) 与COUNT(1) COUNT(1)COUNT(id)COUNT(字段)总结参考 前言
业务开发中#xff0c;我们经常要使用count做一些数据统计。今天根据MySQL5.7官方文档及丁奇老师的MySQL45讲#xff0c;介绍一下COUNT(*)、COUNT(1)、COUNT(id)、COU… 文章目录 前言COUNT(exper)COUNT(*)优化COUNT(*) 与COUNT(1) COUNT(1)COUNT(id)COUNT(字段)总结参考 前言
业务开发中我们经常要使用count做一些数据统计。今天根据MySQL5.7官方文档及丁奇老师的MySQL45讲介绍一下COUNT(*)、COUNT(1)、COUNT(id)、COUNT(字段)效果及性能。
COUNT(exper)
COUNT(exper) 返回由 SELECT 语句检索到的行中expr 非 NULL 值的数量结果是一个 BIGINT 类型的值。如果没有匹配的行结果为0。
COUNT(*)
COUNT(*)它返回的是检索到的行数无论这些行是否包含 NULL 值。
那么问题来了如果SQL中没有WHERE条件只是统计一个总数MySQL为啥不弄总行数计数器需要时直接返回效率肯定高。没错MyISAM引擎就是这做的它把一个表的总行数存在了磁盘上因此执行COUNT(*)的时候会直接返回。
但InnoDB却不能这样做官方也给出了原因 对于事务性存储引擎如InnoDB存储一个精确的行数会有问题的。如果同时发生多个事务每个事务看到的总行数应该是不同的。SELECT COUNT(*) 语句只会计算当前事务可见的行数。存储一个精确的行结果都相同了不能保证事务的隔离性了
优化 在 MySQL 5.7.18 之前InnoDB 通过扫描聚集索引来处理 SELECT COUNT(*) 语句。从 MySQL 5.7.18 开始除非索引或优化器提示指定了使用不同的索引否则 InnoDB 会通过遍历最小的可用二级索引来处理 SELECT COUNT(*) 语句。如果不存在二级索引则会扫描聚集索引。 这是因为聚集索引或叫主键索引叶子节点存储的是数据而二级索引或叫普通索引存储的是主键。二级索引的树磁盘空间是要小于主键索引的遍历需要时间更短。 这里提一下索引字段值为null的情况。在MySQL的InnoDB存储引擎中对于索引中的NULL值处理方式是将所有具有相同NULL值的记录放在索引树的同一位置但并不是说所有的NULL值只占用一个节点。实际上每个包含NULL值的记录都会在索引中有自己的条目这些条目会聚集在一起。
COUNT(*) 与COUNT(1)
二者在操作上是一样的无性能差异。但是前文中提到COUNT(*)有优化所以COUNT(*)应该略快于COUNT(1)
COUNT(1)
InnoDB引擎遍历整张表但不取值。对于返回的每一行放一个 数字“1”进去判断这个值不可能为null累加返回总数。
COUNT(id)
InnoDB引擎会遍历整张表取出每一行的id判断这个值不可能为null累加返回总数。 count(1)不需要取值count(id)需要取值所以count(1)执行得要比count(主键id)快
COUNT(字段)
如果字段定义为NOT NULL。从每一行记录里读出这个字段不会为空直接按行累加返回总数。
如果字段定义为 可为NULL。从每一行记录里读出这个字段值可能为空需要取出这个字段值判断是否为空不为空就累加。
总结
效果上 COUNT(*)COUNT(1)COUNT(id)都是统计满足条件的总行数不考虑是否为null。COUNT(字段)是要考虑是否为空。性能上 COUNT(*)COUNT(1)COUNT(id)COUNT(字段)能用COUNT(*)就用COUNT(*)
个人感觉COUNT(1)和COUNT(id)没有存在必要可以放弃掉这样简单一点哈哈哈哈哈哈
参考
MySQL5.7官方文档