mysql count(*)、count(1) 、count(列名)、count(distinct expr)


概述

  • count(*) :为 SQL92 标准语法,所以数据库都进行过优化;相当于查询整行,不会去掉某个列为空的数据
  • count(1) :实现上与 count(*) 无差别;性能无差别
  • count(列名) :进行全表扫描,判断列名 对应值是不是为NULL,不为NULL则累加,列名 对应值为 null 会不作统计;由于多了一个 是否为NULL 的判断,所以他的性能要比COUNT(*)慢。
  • count(DISTINCT expr,[expr…]):返回具有不同非NULL expr 值的行数的计数。如果没有匹配的行,则 COUNT(DISTINCT)返回 0。

优化

MyISAM

  • MyISAM不支持事务,MyISAM中的锁是表级锁;
  • 因为MyISAM的锁是表级锁,所以同一张表上面的操作需要 串行 进行;
  • 所以,MyISAM做了一个简单的优化,那就是它可以把表的总行数单独记录下来
  • 因为 不会有并发的数据库行数修改,所以查询得到的行数是准确的;
  • 如果从一张表中使用COUNT(* )进行查询的时候,可以直接返回这个记录下来的数值就可以了,当然,前提是不能有where条件。

InnoDB

  • InnoDB支持事务,并且支持行级锁;
  • InnoDB不会在表中保留内部行数,因为并发事务可能同时 “ 看到 ”不同数量的行。因此,SELECT COUNT(*) 语句仅对当前事务可见的行进行计数。
  • 事务中大部分操作都是行级锁,所以可能表的行数可能会被并发修改,就不能做缓存操作了,否则缓存记录下来的总行数就不准确了;
  • 那怎么优化呢?
  • 在InnoDB中,使用COUNT( * )查询行数的时候,不可避免的要进行扫表了,那么,就可以在扫表过程中下功夫来优化效率了。
  • As of MySQL 8.0.13, SELECT COUNT(*) FROM tbl_name query performance for InnoDB tables is optimized for single-threaded workloads if there are no extra clauses such as WHERE or GROUP BY.

  • 从MySQL 8.0.13开始, 确实在扫表的过程中做了一些优化;前提是查询语句中 不包含 WHEREGROUP BY 等条件。
  • COUNT(*)的目的只是为了统计总行数,根本不关心自己查到的具体值;如果能够在扫表的过程中,选择一个成本较低的索引进行的话,那就可以大大节省时间。
  • InnoDB processes SELECT COUNT(* ) statements by traversing the smallest available secondary index unless an index or optimizer hint directs the optimizer to use a different index. If a secondary index is not present, InnoDB processes SELECT COUNT(*) statements by scanning the clustered index.

  • 而 InnoDB中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。相比之下,非聚簇索引要比聚簇索引小很多,所以MySQL会优先选择最小的非聚簇索引来扫表,来减少随机 IO次数,提高效率。
  • 如果索引记录不完​​全在缓冲池中,则 处理语句将花费一些时间;
  • For a faster count, create a counter table and let your application update it according to the inserts and deletes it does. However, this method may not scale well in situations where thousands of concurrent transactions are initiating updates to the same counter table.

  • MySQL 建议我们 : 创建一个计数器表,然后让您的应用程序根据其插入和删除操作对其进行更新。但是,在成千上万的并发事务正在启动对同一计数器表的更新的情况下,此方法可能无法很好地扩展。
  • 所以,当我们建表的时候,创建一个非主键索引还是有必要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值