当前位置: 首页 > article >正文

MySQL45讲 第十四讲 count(*)这么慢,我该怎么办?

文章目录

  • MySQL45讲 第十四讲 count(*)这么慢,我该怎么办?
    • 一、count (*) 实现方式及性能问题
      • (一)不同引擎的实现差异
      • (二)InnoDB 的优化措施
    • 二、计数方案探讨
      • (一)缓存系统保存计数
      • (二)数据库保存计数
    • 三、count 不同用法的性能差别
      • (一)语义解释
      • (二)性能对比
    • 四、总结

MySQL45讲 第十四讲 count(*)这么慢,我该怎么办?


一、count (*) 实现方式及性能问题

(一)不同引擎的实现差异

  1. MyISAM 引擎将表的总行数存储在磁盘上,执行count (*)时可直接返回,效率高。但 MyISAM 不支持事务。如果加了where 条件的话,MyISAM表也是不能返回得这么快的。
  2. 在实际应用中,InnoDB 引擎使用更为广泛。InnoDB引擎执行 count (*)时,需逐行读取数据并累积计数,这是因为在多版本并发控制(MVCC)机制下,不同事务对表总行数的 “可见性” 不同。例如,在一个同时有事务插入数据的场景中,不同时刻启动的事务查询 count (*) 可能得到不同结果,所以 InnoDB只能逐行判断每行记录是否对当前查询可见,进而确定总行数。

(二)InnoDB 的优化措施

  1. InnoDB 是索引组织表,普通索引树比主键索引树小。对于 count (*) 操作:
    • MySQL优化器会选择遍历最小的索引树以减少扫描数据量。然而,即便如此,随着表中记录数增多,直接使用 count (*) 仍会导致性能问题。
    • show table status 命令虽执行快,但其中的TABLE_ROWS 值是通过采样估算得来,误差可达 40% - 50%,不能准确替代 count (*) 使用。

二、计数方案探讨

(一)缓存系统保存计数

  1. 对于更新频繁的库,可使用 Redis 等缓存系统保存表的总行数,表数据插入或删除时相应更新 Redis 计数。但这种方式存在问题:
    • 缓存系统可能丢失更新。即使将 Redis 数据持久化存储,仍可能因异常重启等情况丢失计数更新操作
    • 逻辑上不精确。在并发系统中,由于操作顺序难以精确控制,可能出现数据不一致情况,如页面显示的记录与 Redis 计数不匹配。

(二)数据库保存计数

  1. 将计数直接存于数据库单独的计数表 C 中,利用 InnoDB 支持事务的特性,可解决崩溃丢失问题。在事务执行过程中,通过合理的事务隔离机制,可确保计数与表数据在逻辑上的一致性,避免了缓存系统中因并发操作导致的计数不精确问题。

三、count 不同用法的性能差别

(一)语义解释

  1. count () 是聚合函数,对于返回结果集逐行判断,参数非 NULL 时累计值加 1。count (*)、count (主键 id) 和 count (1) 都返回满足条件结果集的总行数,count (字段) 返回满足条件数据行中参数 “字段” 不为 NULL 的总个数。

(二)性能对比

  1. 对于 count (主键 id),InnoDB 引擎遍历整张表取每行 id 值返回给 server 层,server 层判断非空后累加,涉及解析数据行和拷贝字段值操作:
    • count (1) 则遍历整张表但不取值,server 层每行放数字 “1” 判断非空后累加,所以 count (1) 比 count (主键 id) 执行快。
    • count (字段) 若字段定义为 not null,逐行读取判断非空累加,若字段允许为 null,还需取值进一步判断,性能较差。
    • count (*) 专门优化不取值,按行累加,效率较高。建议尽量使用 count (*)
  2. 按照效率排序的话,count(字段)<count(主键id)<count(1)≈count(*),所以尽量使用count(*)

四、总结

  1. MySQL 中不同引擎 count (*) 实现方式不同,InnoDB 因 MVCC 机制不能像 MyISAM 直接返回总行数
  2. 在处理频繁变更且需统计表行数的需求时,Redis缓存系统保存计数虽读写快但存在丢失更新和逻辑不精确问题。而在数据库中利用事务特性,把这个计数直接放到数据库里单独的一张计数表C中,保存计数可解决一致性问题。
  3. 同时,了解 count 不同用法性能差别有助于优化查询语句,count(字段)<count(主键id)<count(1)≈count(*),在实际应用中应根据具体需求选择合适的计数方案,充分发挥 InnoDB 引擎事务特性简化业务逻辑,确保数据的准确性和系统性能。

http://www.kler.cn/a/380239.html

相关文章:

  • Python毕业设计选题:基于django+vue的4S店客户管理系统
  • Vehicle OS软件平台解决方案
  • Windows换机华为擎云(银河麒麟V10+麒麟9000C CPU)后,使用selenium的程序怎么办(20241030)
  • 光耦合器的关键作用和创新---腾恩科技
  • 解决 ClickHouse 高可用集群中 VRID 冲突问题:基于 chproxy 和 keepalived 的实践分析
  • 基于人脸识别PCA算法matlab实现及详细步骤讲解
  • 细腻的链接:C++ list 之美的解读
  • 【机器学习】音乐与AI的交响:机器学习在音乐产业中的应用
  • 爬虫学习2
  • 【热门主题】000029 ECMAScript:现代编程的基石
  • 【递归】——五道经典链表与递归问题的深度解析
  • stuid学生信息
  • 第十二章 spring Boot+shiro权限管理
  • 【django】django RESTFramework前后端分离框架快速入门
  • 一阶 RC 低通滤波器实验方案
  • MFC图形函数学习05——画椭圆函数
  • 推荐一款高级的安装程序打包工具:Advanced Installer Architect
  • 用Python遍历输出烟感名称和状态
  • 简单说明vuex
  • AIDOVECL数据集:包含超过15000张AI生成的车辆图像数据集,目的解决旨在解决眼水平分类和定位问题。
  • SwiftUI:单个App支持设置多语言
  • 【零基础学习CAPL】——使用CAP测试报文长度DLC
  • 交换机的基本配置
  • MySql创建用户与授权
  • 关于安科瑞电能质量监测和治理产品在分布式光伏电站的应用探讨
  • 又一次安装autoware.universe的过程