myIsam引擎把一个表的总行数存在了磁盘上,因此执行count(*)会直接返回结果,效率很高 #但是myisam不支持事物
innodb引擎需要把数据一行行从引擎里读出来,然后计数累加。
innodb由于多版本并发控制机制,同一时刻不同回话拿到的结果可能都不相同,所以不能直接将总行数存储在磁盘上。
比如同一时刻执行了三个会话 :
A会话: select count(*) from t #比如返回值为10
B会话: begin insert into 一条数据 ; select count(*) from t #返回值为11
C回话: insert into 俩条数据 ; select count(*) from t #返回值12
show table status 返回字段 TABLE_ROW用于显示这个表当前有多少行,但是由于索引统计的值是通过采样来估算的,所以不准确。
小结:
myisam统计行数效率快,但是不支持事物
show tables status统计行数,结果不准确,精确度仅有百分之50左右
innodb引擎统计行数,会遍历全表,结果精确,但是太耗费性能。
给出的解决方案:
通过在数据库中建表保存计数,利用innodb引擎支持事物的优点,保持数据在逻辑上一直的前提下,快速获取结果。
count():mysql聚合函数,对返回的结果集一行行判断,不是null,累计值就+1,不是就不+。最后返回累计值。
不同count()的用法:
count(主键id),innodb会遍历整张表,将主键id上的值都取出来,返回给server层,server层判断不为null的前提下,按行累加
count(1),innodb遍历整张表,不取值。返回给server层,server层对于返回的每一行,都会放一个数字1 进去,不为空的话按行累加
count(字段),看字段默认是否允许为null,分别进行判断
count(*),不会将全部字段取出来,专门做了优化,不取值。肯定不是null,按行累加
性能:count(*)>count(1)>count(主键)>count(字段)