mysql innodb count,innodb中count(*),count(字段),count(主键id),count(1)的区别

count(参数)函数解释

count() 是一个聚合函数,对于返回的结果集,一行一行的判断,函数参数不是NULL时累计值就加1,否则不加,最后返回累计值。

没有过滤条件时,myisam中把一个表的总数存在磁盘上,执行count(*)直接返回这个数,效率很高。innodb中需要把数据一行一行的从引擎中读出来,然后累计。

count()各种用法对比

根据函数解释可以知道,count(*),count(1),count(主键id)都表示满足条件的总行数,而count(字段)表示满足条件的总行数里面参数 “字段” 不为NULL的总个数。

count(主键id)

innodb会遍历整张表,把每一行的id取出来,返回给server层,server层拿到id后,判断不可能为NULL,就按行累加。

count(1)

innodb会遍历整张表,但不取值,server层对于返回的每一行,放一个数字1进去,判断不可能为NULL,按行累加。

count(字段)

如果字段定义为not null,一行行的从记录中读出这个字段,判断不可能为空,按行累加。

如果字段定义允许为null, 执行时需要先把值取出来进行判断,判断不是null才累加。

count(*)

不会把字段全部取出来,而是专门做了优化,不取值,因为肯定不是null,直接按行累加。

操作

是否取值

是否判断

备注

count(*)

最快

count(1)

count(主键id)

可能使用最小的索引树

count(字段)

字段上无索引时,只能选主键索引

效率对比

count(字段)< count(主键id) < count(1)≈count(*)

为什么innodb中没有把表记录总数存储起来?

因为即使同一时刻的多个查询,多版本并发控制(MVCC)的原因,表中总记录数是不确定的,各个事务中得到的结果可能也不一样。

比如在可重复读的隔离级别下,每一行记录要判断这个记录对这个会话是否可见,因此对count(*)请求来说,innodb只好把数据一行一行读出并做出判断,可见的行才能用于当前查询。

MySQL如何对count(*) 操作的优化的?

由于innodb中主键索引树的叶子节点是数据,普通索引树的叶子节点是主键值,因此普通索引比主键索引小很多。对于conut(*)遍历那个索引树得到的结果逻辑上都是一样的,因此MySQL优化器会找到最小的那个树去遍历。

在保证逻辑正确的前提下, 尽量减少数据的扫描,是数据库设计的通用法则之一。

show table status输出的总行数TABLE_ROWS 能替代count(*)吗?

不能。TABLE_ROWS是通过采样估算出来的,因此这个值很不准确。官方文档描述误差可达到40%-50%

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL ,自增字段通常是主键字段。如果你想实现非主键字段的自增,可以通过触发器来实现。具体步骤如下: 1. 创建一个表,并定义一个非主键字段作为自增字段。 ``` CREATE TABLE `test_table` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `count` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ``` 2. 创建一个 BEFORE INSERT 触发器,当插入数据时,自动将 count 字段加 1 并将结果赋值给 count 字段。 ``` CREATE TRIGGER `test_table_auto_increment` BEFORE INSERT ON `test_table` FOR EACH ROW BEGIN SET NEW.count = ( SELECT IFNULL(MAX(count) + 1, 1) FROM test_table ); END; ``` 这个触发器会在每次插入数据之前自动执行,将 count 字段自增。 3. 插入数据,测试触发器是否生效。 ``` INSERT INTO `test_table` (`name`) VALUES ('test1'); INSERT INTO `test_table` (`name`) VALUES ('test2'); INSERT INTO `test_table` (`name`) VALUES ('test3'); SELECT * FROM `test_table`; ``` 输出结果如下: ``` +----+-------+-------+ | id | name | count | +----+-------+-------+ | 1 | test1 | 1 | | 2 | test2 | 2 | | 3 | test3 | 3 | +----+-------+-------+ ``` 可以看到,count 字段已经自增了。 注意事项: - 触发器的语句必须以分号结束。 - 触发器的查询语句必须使用 IFNULL 函数来处理空值。 - 触发器的查询语句必须使用 MAX 函数来获取当前表 count 字段的最大值。 - 触发器的 NEW 关键字表示插入操作的新数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值