count(*)/count(1)/count(主键)统计效率对比

本文通过实验对比COUNT(1), COUNT(*)与COUNT(主键)及COUNT(非主键)在MySQL 5.7 InnoDB引擎下的性能差异,揭示了COUNT函数的实际执行效率,并解析不同场景下COUNT函数的行为特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在实际业务开发中,我们常常需要count数据表的记录条数。关于使用mysql的count统计函数,大多开发者都不会有疑问,但是就使用细节上,大家的观点可能就不一致了。一派认为count(1)比count(*)要快,说count(*)要全表扫描而count(1)则不用。另一派反之。针对count(主键)和count(1)和count(*),大家几乎一致认为count(主键)效率较慢。那么实际情况是这样么?

本次就来做个总结。

测试

针对mysql5.7 innodb引擎,主键为id的表,
我们explain count(1)和count(*)以及count(id)和count(name)

explain select SQL_NO_CACHE count(1) from province
explain select SQL_NO_CACHE count(*) from province
explain select SQL_NO_CACHE count(id) from province
explain select SQL_NO_CACHE count(name) from province

然后发现前三者的执行计划一摸一样
1.png
而count(name)显然效率较低
2.png

所以我们确定count(*)和count(1)以及count(主键)的效率是一致的!
mysql底层对count()有优化,会选择最有效率的方式去执行count操作,两者没有性能差异,效率都比较高。

总结

一方面

count(主键列),count(),count(1)效率差不多!
count(非主键列)的效率往往低于count(
),count(1),count(主键列)!

另一方面

count(1),count(*)会统计表中的所有的记录数,包含字段为null 的记录;
count(列名) 会统计该字段在表中出现的次数,不统计字段为null 的记录。

请关注我的订阅号

订阅号.png

private JSONString insertDao(PoOrderParam param) { BaseDAO baseDAO = new BaseDAO(); // 2. 生成主键和必要字段 String pk_group = "0001L11000000000XXXX"; // 替换为实际集团主键 // 3. 构建 SQL String sql = "INSERT INTO po_order (" + "PK_ORDER, PK_GROUP, PK_ORG_V, CTRANTYPEID, VBILLCODE, DBILLDATE, " + "PK_SUPPLIER, CORIGCURRENCYID, CEMPLOYEEID, PK_DEPT_V, NTOTALASTNUM, " + "NTOTALORIGMNY, FORDERSTATUS, NVERSION, VMEMO, BILLMAKER, DMAKEDATE, " + "APPROVER, TAUDITTIME, CREATOR, CREATIONTIME, MODIFIER, DR, BSOCOOPTOME" + ") VALUES (" + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 'N')"; // DR=0, BSOCOOPTOME='N' // 4. 参数处理 Object[] params = new Object[] { param.getId(), pk_group, param.getPk_org_v(), param.getCtrantypeid(), param.getVbillcode(), new UFDate(param.getDbilldate()).toString(), // UFDate转字符串 param.getPk_supplier(), param.getCorigcurrencyid(), param.getCemployeeid(), param.getPk_dept_v(), param.getNtotalastnum() != null ? new UFDouble(param.getNtotalastnum()) : UFDouble.ZERO_DBL, param.getNtotalorigmny() != null ? new UFDouble(param.getNtotalorigmny()) : UFDouble.ZERO_DBL, param.getForderstatus() != null ? Integer.parseInt(param.getForderstatus()) : 0, param.getNversion() != null ? param.getNversion().intValue() : 1, param.getVmemo(), param.getBillmaker(), new UFDate(param.getDmakedate()).toString(), // UFDate转字符串 param.getAuditor(), new UFDate(param.getTaudittime()).toString(), // UFDate转字符串 param.getCreator(), new UFDateTime(param.getCreationtime()).toString(), // UFDateTime转字符串 param.getModifier() }; // 5. 执行插入 try { int count = baseDAO.executeUpdate(sql,params); if (count > 0) { return RestUtils.toJSONString("插入成功,单据ID:" + param.getId()); } else { return RestUtils.toJSONString("插入失败"); } } catch (BusinessException e) { throw new RuntimeException("数据库操作失败", e); } } 我想用这个但是baseDAO.executeUpdate(sql,params);参数对不上 public int executeUpdate(String sql, SQLParameter parameter) /* */ throws DAOException /* */ { /* 129 */ PersistenceManager manager = null; /* */ int value; /* */ try { /* 132 */ manager = createPersistenceManager(dataSource); /* 133 */ JdbcSession session = manager.getJdbcSession(); /* 134 */ value = session.executeUpdate(sql, parameter); /* */ } /* */ catch (DbException e) { /* 137 */ Logger.error(e.getMessage(), e); /* 138 */ throw new DAOException(e.getMessage()); /* */ } finally { /* 140 */ if (manager != null) /* 141 */ manager.release(); /* */ } /* 143 */ return value; /* */ } /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ public int executeUpdate(String sql) /* */ throws DAOException /* */ { /* 156 */ PersistenceManager manager = null; /* */ int value; /* */ try { /* 159 */ manager = createPersistenceManager(dataSource); /* 160 */ JdbcSession session = manager.getJdbcSession(); /* 161 */ value = session.executeUpdate(sql); /* */ } /* */ catch (DbException e) { /* 164 */ Logger.error(e.getMessage(), e); /* 165 */ throw new DAOException(e.getMessage()); /* */ } finally { /* 167 */ if (manager != null) /* 168 */ manager.release(); /* */ } /* 170 */ return value; /* */ } 他只有这两个方法 参数对不上
最新发布
05-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码哥说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值