mysql Innodb单表31m千万级数据count计数方案及调优

MySQL命令行操作全指南:从基础连接到性能调优实战 数据库管理系统是后端开发的核心组件,它通过结构化查询语言(SQL)实现数据的存储、检索和管理。其工作原理基于客户端-服务器模型,客户端发送指令,服务器处理并返回结果。掌握命令行操作对于深入理解数据库运行机制、实现自动化运维和高效性能调优具有重要技术价值,尤其在服务器环境、脚本编写和复杂问题排查等应用场景中不可或缺。本文将系统介绍MySQL命令行客户端的安装连接、数据库与表操作、CRUD实战、权限管理以及性能排查等核心内容,帮助开发者建立对数据库的“直接掌控感”,并通过慢查询分析、执行计划优化等实战技巧提升数 阅读详情

ENV

  1. 线上环境为RDS,版本5.7.15

    select version()
    output:
    5.7.15-log
  2. 测试环境为docker搭建的mysql,版本5.7.19

    select version()
    output:
    5.7.19
  3. 单表3000万+的class表以及20万+的学校表,需要使用count查询实时数量用于分页,延迟不能太高,否则影响业务
  4. 因需要使用事务功能,使用存储引擎为Innodb(MyISAM count是自动计数单独保存,Innodb需要每次扫描表进行统计)
  5. 本文使用class表进行示例表述,school同理

OPTIMIZE

一. 出现的第一个问题是RDS线上mysql的查询速度始终没有测试库的快,相同的数据和存储结构,索引数据都相同(一开始线上使用count完全不能查询,会出现等待超时).
1. 查看索引

show index from consumer.class;
output:
'class', '0', 'PRIMARY', '1', 'id', 'A', '28663646', NULL, NULL, '', 'BTREE', '', ''
'class', '0', 'UQE_class_loginName', '1', 'loginName', 'A', '28663646', NULL, NULL, 'YES', 'BTREE', '', ''
'class', '1', 'IDX_class_school_id', '1', 'school_id', 'A', '211268', NULL, NULL, '', 'BTREE', '', ''
'class', '1', 'grade_id', '1', 'grade_id', 'A', '8644', NULL, NULL, 'YES', 'BTREE', '', ''
'class', '1', 'schuid', '1', 'schuid', 'A', '216557', NULL, NULL, 'YES', 'BTREE', '', ''

2. 测试时间

set profiling = 1;
SELECT count(*) FROM consumer.class;
show profiles;

3. 分别分析sql的执行

explain select count(*) from consumer.class ;
test output:
'1', 'SIMPLE', 'class', NULL, 'index', NULL, 'IDX_class_school_id', '4', NULL, '28663646', '100.00', 'Using index'
online output:
1
1
SIMPLE
null
null
null
null
null
null
null
null
null
Select tables optimized away

发现线上版本的mysql是经过自己编译器优化的Select tables optimized away,但是效率确实低到不能接受(单独这样查询几分钟过后仍然查不出来,并且显示超时),这是因为mysql5.7.*版本机制相关的问题,具体可参考:
https://bugs.mysql.com/bug.php?id=80580
https://stackoverflow.com/questions/27377549/select-count-not-using-index
4. 强制使用索引,解决了上面线上查询几分钟仍不能查询到结果后返回超时的问题

select count(`id`) from consumer.class force index(primary) where id > 0
explain select count(`id`) from consumer.class force index(primary) where id > 0

但是线上RDS速度仍然不尽人意,需要大概2分多钟,而测试自建的在10-20秒,目前猜测是因为线上RDS使用的是机械硬盘,而我们测试环境自建的为SSD.因为是阿里云的RDS,所以不知道内部做了些什么处理.
5. 使用mysql 事件和触发器解决,定时执行事件event进行统计并插入一个专门用于记录的统计表,然后触发器监听指定表的insert和delete操作,分别对记录进行加1和减1.
可参考我如下sql创建:

use consumer;
CREATE TABLE `class_count` (
  `key` varchar(50) NOT NULL,
  `value` varchar(100) NOT NULL,
  PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `school_count` (
  `key` varchar(50) NOT NULL,
  `value` varchar(100) NOT NULL,
  PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

drop event `consumer`.`update_class_count_1`;
CREATE EVENT `consumer`.`update_class_count_1` 
  ON SCHEDULE EVERY 10 day
  STARTS  '2017-09-22 01:00:00'  ON COMPLETION NOT PRESERVE  
  ENABLE  
  DO INSERT INTO consumer.class_count (`key`, `value`)
  VALUES ('cal_count',(select count(*) from consumer.class force INDEX (IDX_class_school_id) where `school_id` != 0))
  ON DUPLICATE KEY UPDATE value=VALUES(value);


  drop event `consumer`.`update_school_count`;
CREATE EVENT `consumer`.`update_school_count` 
  ON SCHEDULE EVERY 10 DAY
  STARTS  '2017-09-22 18:16:04'  ON COMPLETION NOT PRESERVE  
  ENABLE  
  DO INSERT INTO consumer.school_count (`key`, `value`)
  VALUES ('cal_count', (select count(`id`) from consumer.school_login force index(primary) where id > 0))
  ON DUPLICATE KEY UPDATE value=VALUES(value);



  DROP TRIGGER IF EXISTS `consumer`.`count_down_class`; 
CREATE  TRIGGER `consumer`.`count_down_class` 
AFTER DELETE  ON consumer.class
 FOR EACH ROW  
UPDATE `class_count`
SET 
  `class_count`.`value` = `class_count`.`value` - 1 
WHERE
  `class_count`.`key` = "cal_count"; 


  DROP TRIGGER IF EXISTS `consumer`.`count_down_school`; 
CREATE  TRIGGER `consumer`.`count_down_school` 
AFTER DELETE  ON consumer.school_login
 FOR EACH ROW  
UPDATE `school_count`
SET 
  `school_count`.`value` = `school_count`.`value` - 1 
WHERE
  `school_count`.`key` = "cal_count"; 



  DROP TRIGGER IF EXISTS `consumer`.`count_up_class`; 
CREATE  TRIGGER `consumer`.`count_up_class` 
AFTER INSERT  ON consumer.class
 FOR EACH ROW  
UPDATE `class_count`
SET 
  `class_count`.`value` = `class_count`.`value` + 1 
WHERE
  `class_count`.`key` = "cal_count"; 


DROP TRIGGER IF EXISTS `consumer`.`count_up_school`; 
CREATE  TRIGGER `consumer`.`count_up_school` 
AFTER INSERT  ON consumer.school_login
 FOR EACH ROW  
UPDATE `school_count`
SET 
  `school_count`.`value` = `school_count`.`value` + 1 
WHERE
  `school_count`.`key` = "cal_count"; 

这里线上RDS特别需要注意,我也是看了好久,因为mysql开启event必须设置SET GLOBAL event_scheduler = 1; 开启事件功能,否则就算创建了也不会生效,而RDS执行这个sql指令的时候,一直提示我没有super权限(测试库自建的mysql可以直接设置),但是我确实是使用root用户登录的,后来在DMS的RDS的管理界面看到有此参数配置,手动修改下就生效了.完成后可以使用SHOW VARIABLES LIKE ‘event_scheduler’,需要看到’event_scheduler’, ‘ON’,最后检查下events和triggers有没有创建好

SHOW TRIGGERS;
SHOW EVENTS;

另外,count(),count(1) 和 count([column])我这里经过测试,两者执行时间基本一致,查阅相关资料发现mysql解释器会自动优化count(),所以从执行效率上说count(),count(1)和count([column])实际执行效率几乎相同,都是经过了解释器优化的.而”InnoDB handles SELECT COUNT() and SELECT COUNT(1) operations in the same way. There is no performance difference.”,即count(*) = count(1) 计数包括null,count([column])计数不包括null,可参阅mysql 5.6中文档:
https://dev.mysql.com/doc/refman/5.6/en/innodb-restrictions.html
https://dev.mysql.com/doc/refman/5.6/en/group-by-functions.html#function_count
注意:使用offset的时候,因为mysql不知道数据表的行数据是否连续,所以需要遍历数据表进行查找,offset的值越大,查询的速度耗时越长,我这里limit 20 offset 30579060,耗时约60-70秒,如果不要求精确度,可以用where id来进行获取,这样就不会从头遍历到offset 30579060,当然如果业务允许的情况,比如如果不使用innode的事务,更倾向使用MYISAM的话,将会是一个更好的解决方案

REFERENCES

  1. https://stackoverflow.com/questions/19267507/how-to-optimize-count-performance-on-innodb-by-using-index?noredirect=1&lq=1
MySQL核心点笔记 条件查询 -- 1、关系运算符:> < >= <= = <> (也可以用!=,是一种宽容处理,不建议) select count(last_name),last_name,first_name FROM employees WHERE salary<>20000 -- 聚集函数只能显示一行 -- 2、按逻辑表达式筛选:and or -- 3、范围表达式:between and,not between and -- 4、确定集合:in,not in --... 阅读详情

相关推荐

Ubuntu 20.04 Swap 精准调优:从容量计算到 swappiness 与 vfs_cache_pressure 协同治理

Swap 是 Linux 内存管理的核心机制,本质是内核在物理内存紧张时对匿名页和页缓存进行回收与换出的策略执行器,而非简单的‘备用内存’。其性能表现直接受 swappiness(控制匿名页换出倾向)和 vfs_cache_pressure(调控目录项/索引缓存回收强度)双重影响。科学配置 Swap 不仅能避免 OOM Killer 误杀进程、降低 MySQL 8.0.25 查询延迟波动,还可缓解 VINS-Mono 轨迹漂移、改善桌面响应卡顿等典型场景问题。本文基于 Ubuntu 20.04 实际部署经验

weixin_33888907的博客 404

mysql千万级别的数据使用count(*)查询比较慢怎么解决?

当MySQL中的数据量达到千万级别时,使用COUNT()查询可能会变得比较慢。一些优化COUNT(*)查询的方法:使用索引、使用近似值、使用缓存、分批查询、数据分片等技术来解决问题

Harry的博客 1万+

MySQL 8.0.30+ redo log 新特性解析:innodb_redo_log_capacity 如何替代旧参数管理日志文件组

本文深入解析MySQL 8.0.30+引入的redo log新特性innodb_redo_log_capacity,详细对比新旧参数管理方式的差异,揭示新参数如何简化日志文件组管理、支持动态调整并提升性能。通过容量规划公式、场景化配置建议和实战迁移指南,帮助DBA高效利用这一革新特性优化数据库运维。

cuyi7076的博客 542

MySQL 百万级/千万级表 总记录数查询

基于 InnoDB 存储引擎的表,在数据量达到百万级之后,用 count 函数查询表记录总数会变得很慢,会导致服务请求超时。针对这种情况总结下我所想到的解决办法。针对百万级及其以上的表数据记录总数通过MySQL数据管理系统自带库表,查询指定schema和table_name的记录总数。前提条件:表主键id 必须使用自增长,且必须确保表中数据几乎没有跳id、删数据的情况下,直接用最大id,减最小id。温馨提示:这里是个预估值,但与实际表记录总数非存在差别,由于MySQL数据管理系统需要定时更新表的记录总数。

zhouzhiwengang的专栏 6567

MySQL数据库

MySQL 基础知识点摘要 查询语句区别 WHERE vs HAVING:WHERE在分组前过滤行,不能直接使用聚合函数;HAVING在分组后过滤分组数据,可使用聚合函数 UNION vs UNION ALL:UNION自动去重但性能较慢,UNION ALL保留所有记录且性能更快 IN vs EXISTS:IN先执行子查询再匹配,适合主查询结果集大;EXISTS主查询每行执行子查询,适合主查询结果集小 数据操作区别 DELETE:删除指定行,记录日志,不重置自增ID,空间标记为可重用 TRUNCATE:清空

weixin_54017681的博客 383

给硬件工程师的UCIe软件配置入门:从寄存器表到实战调试,一篇讲透

本文为硬件工程师提供UCIe软件配置的全面指南,从寄存器表解析到实战调试技巧,涵盖链路训练、错误排查等关键环节。通过详细代码示例和分层诊断法,帮助工程师快速掌握UCIe寄存器访问机制,提升异构集成开发效率。

weixin_30268921的博客 313

MySQL 中 count(*) 千万级别数据查询

MySQL中count(*)千万级别数据查询优化

lixiaoyu123456的博客 6929

详细教程:如何使用elasticsearch 8.x进行向量搜索

大模型的热度使得向量数据库和embedding也成了ai领域的热门话题,有别于从头开始训练一个大模型或基于基础模型进行微调的方式,embedding检索相关上下文是对大模型进行定制的各种方法中成本最低、技术实现最便捷的方式。从技术实现的角度,

qq_50790981的博客 1万+

Mysql 千万级数据库表 count()问题

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33963189的博客 770

从报错到优化:一次Gauss JDBC参数限制排查实录(32767参数上限避坑指南)

本文详细记录了排查GaussDB JDBC驱动因绑定参数数量超过32767上限而抛出`PSQLException`(报错信息为`Tried to send an out-of-range integer as a 2-byte value`)的全过程。文章深入分析了该限制的底层协议原理,并提供了应用层分批查询、使用临时表以及优化业务逻辑等多种解决方案,旨在帮助开发者规避此参数上限陷阱,构建更稳健的数据访问层。

rgv23456789的博客 220

STM32F407 UART4串口DMA收发实战:告别频繁中断,用空闲中断+DMA搞定不定长数据

本文详细介绍了STM32F407 UART4串口结合DMA和空闲中断实现高效不定长数据收发的实战方案。通过DMA硬件级数据搬运和空闲中断智能帧检测,显著降低CPU占用率,提升通信效率,适用于工业传感器数据采集和智能设备通信场景。

weixin_42631411的博客 158

mysql 千万级的 count统计对比

在统计查询的时候尽量使用count(id),不要使用count(*)这样的;特别是数据量特别大的时候。

上班搞IT,下班搞ITF。 7308

VSCode配置C/C++语言环境(小白专用保姆教程)(超细)

VSCode配置C/C++语言环境(小白专用保姆教程)(超细)

ITQWQ的博客 8229

Mysql千万级别数据优化方案

目录 目录... 1 一、         目的与意义... 2 1)     说明... 2 二、         解决思路与根据(本测试表中数据在千万级别)... 2 1)     建立索引... 2 2)     数据体现(主键非索引,实际测试结果   其中fid建立索引)... 2 3)     MySQL分页原理... 2 4)    

stay hungry,stay foolish ! 435

STLink驱动安装全攻略:从卸载到Keil配置的完整避坑指南

本文提供了STLink驱动安装与Keil环境配置的完整避坑指南。详细讲解了从驱动卸载、重装到Keil调试器设置的每一步,并针对常见的设备无法识别、连接不稳定等问题给出了深度解决方案,帮助开发者快速搭建稳定的STM32开发环境。

weixin_29182481的博客 426

C语言 100道经典编程题适用于专升本,专接本【详细分析版】_c语言专升本题目

/法2//left指向起始 right指向数组末尾= 0){left++;//如果*left是奇数就循环接着向后指,直到指向偶数就退出//(left

2401_84978503的博客 696

MySQL数据库开发实战:从SQL语法到索引优化与性能调优

在实际数据库开发中,很多开发者都经历过从只会写简单增删改查,到需要面对复杂查询、性能瓶颈和线上问题的阶段。MySQL作为最流行的开源关系型数据库,其核心在于如何高效、正确地使用SQL,并理解其背后的执行逻辑。本文旨在为希望系统掌握MySQL的开发者提供一个从环境搭建、语法入门到实战优化的清晰路径。我们将从最基础的安装配置开始,逐步深入到SQL核心语法、索引原理、查询优化以及生产环境常见问题的排查,目标是让你不仅能写出正确的SQL,更能写出高效的SQL,并具备初步的线上问题分析能力。 1. 理解MySQL:从

weixin_33672400的博客 498

GPU架构(1.1)--介绍 GPU的 VPU(Vision Processing Unit)架构

基于自研的 VPU(Vision Processing Unit)架构,专为高性能图形处理和深度学习设计。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。这种架构不仅适用于高性能图形处理,还广泛应用于深度学习、科学计算和边缘计算等领域。通过了解 VPU 架构的详细设计和工作原理,读者可以更好地利用这些先进的 GPU 技术,开发出高效、可靠的计算系统。

MHD0815的博客 1301

Ubuntu 18.04 部署 Galera 集群的系统级调优指南

Galera Cluster 是基于同步复制与事务认证(Certification-Based Replication)的多主 MySQL 高可用方案,其稳定运行高度依赖操作系统底层支持。不同于普通 MySQL 部署,Galera 对文件描述符、内存映射(mmap)、TCP 连接复用、时间同步及 AppArmor 权限等有严苛要求。在 Ubuntu 18.04 这一经典 LTS 版本中,systemd 资源限制、默认内核参数与安全策略常导致节点无法加入、SST 失败或脑裂。本文聚焦于生产环境必需的系统级调优

weixin_33889665的博客 478

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

JB2-3-MySQL(一)

关系型DB,存储引擎,组织架构,MySQL容器,可视化工具,导入导出表格,DDL用户,DCL权限,DDL三范式,DDL表格,DDL临时表,DML操作,DDL约束,DQL查询(排序,条件,模糊,正则,范围,分页,分组,子查询,联表,并集),DQL函数(数学,日期,字符,自定义)等。

周航宇的博客 3608

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

MySQL

MYSQL

weixin_43766298的博客 1235

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

知识体系之MySQL

mysql

JaweG 5251

Mysql基础整理

一、基本使用 cls 清屏(windows) ctrl + l 清屏(linux) 1、开启或关闭mysql服务 (1)windows:超级管理员权限下才能使用 ​ 启动mysql:net start mysql ​ 停止mysql:net stop mysql (2)linux:直接启动即可 ​ 启动mysql:service mysql start ​ 停止mysql:service mysql stop ​ 重启mysql:service mysql restart 2、基

有用的话关个注,点个赞,收个藏🫶。 448

mysql数据库的了解和使用

mysql数据库的了解和使用

xgq_111的博客 2030

MySQL的数据类型

mysql数据类型简介 表类型 MySQL的数据表类型很多,其中比较重要的是MyISAM,InnoDB这两种。 这两种类型各有优缺点,需要根据实际情况选择适合的,MySQL支持对不同的表设置不同的类型。下面做个对比: MyISAM表类型是一种比较成熟稳定的表类型,但是MyISAM对一些功能不支持。              MyISAM                 InnoDB

1205

《Java 100 天进阶之路》第89篇:MySQL面试压轴题(2026版)

摘要:覆盖存储引擎、事务MVCC、锁机制、SQL优化与工具链、高可用架构、分库分表等 45+ 道高频面试题。深度剖析 InnoDB vs MyISAM、MVCC 原理、死锁排查、深分页优化,并新增 AI 辅助慢 SQL 诊断、Optimizer Trace / 直方图调优、云原生 Serverless 数据库选型 等 2026 前沿视角。每个考点配套标准话术 + 加分回答 + 实战经验。面试突击,这一篇就够了。

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 4882
上一篇: opensuse下安装网易云音乐netease-cloud-music
下一篇: 手动搭建高可用的kubernetes 集群
anteoy
博客等级 码龄10年 24粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值