MySQL 5.7下InnoDB对COUNT(*)的优化

简介:

0、导读

饱受诟病的InnoDB表COUNT(*)性能问题在5.7下做了优化,果真如此吗?

1、经典需求:InnoDB表COUNT(*)

InnoDB引擎表经常被抱怨执行COUNT(*)的效率太差,因此此类需求通常会被建议用其他方法来满足,比如另外加一个计数器表,或者用SHOW TABLE STATUS查看大概数量。

不过,从MySQL 5.7.2起,这个问题得到了解决,我们来看看。

2、MySQL 5.7版本InnoDB对COUNT(*)的优化

MySQL每发布一个新版本,都会放出相应的Release Notes,我们注意到5.7.2版本的发布说明中提到:

InnoDB: SELECT COUNT(*) FROM t statements now invoke a single handler call to the storage engine to scan the clustered index and return the row count to the Optimizer. Previously, a row count was typically performed by traversing a smaller secondary index and invoking a handler call for each record. A single handler call to the storage engine to count rows in the clustered index generally improves SELECT COUNT(*) FROM t performance. However, in the case of a large clustered index and a significantly smaller secondary index, performance degradation is possible compared to performance using the previous, non-optimized implementation. For more information, see Limits on InnoDB Tables.

简单地说就是:COUNT(*)会选择聚集索引,进行一次内部handler函数调用,即可快速获得该表总数。我们可以通过执行计划看到这个变化,例如:

很明显,在查询优化器阶段就已经得到优化了,相比效率应该杠杠的吧,我们稍后再来对比看看。

补充说下,5.7以前的版本中,COUNT(*)请求通常是:扫描普通索引来获得这个总数。也来看看5.6下的执行计划是怎样的:

可以看到,可以利用覆盖索引来完成COUNT(*)请求。

3、对比测试

先看一组测试数据:

count(*)对比测试

MySQL 5.6.33

MySQL 5.7.15

相差

表数据量

8976914

9000270

100.26%

耗时(秒)

5.459952

1.142340

20.92%

可以看到,两次数据量相当,但SQL耗时5.7约只有5.6的1/5,这个效率还是不错的吧。

我们来看看5.6和5.7版本下的status和profiling对比情况:

4、别高兴得太早

看完上面的对比测试,相信您已经心动了吧,但还别高兴得太早哦,官方文档里其实埋了一个伏笔:

InnoDB: SELECT COUNT(*) FROM t statements now invoke a single handler call to the storage engine to scan the clustered index and return the row count to the Optimizer. Previously, a row count was typically performed by traversing a smaller secondary index and invoking a handler call for each record. A single handler call to the storage engine to count rows in the clustered index generally improves SELECT COUNT(*) FROM t performance. However, in the case of a large clustered index and a significantly smaller secondary index, performance degradation is possible compared to performance using the previous, non-optimized implementation. For more information, see Limits on InnoDB Tables.

简言之,就是说如果聚集索引较大(或者说表数据量较大),没有完全加载到buffer pool中的话,有可能反而会更慢,还不如用原先的方式。

下面我们来测试下,读取tpcc测试表stock,该表有1亿行记录,表空间文件约65GB,而innodb buffer pool只分配了12G,这时候再看下对比数据:

count(*)对比测试

MySQL 5.6.33

MySQL 5.7.15

相差

表数据量

1亿

1亿

0.00%

耗时(秒)

693.66

5331.69

768.63%

在这种情况下,5.7版本反而慢的夸张,悲剧啊~

那么在5.7下的大表,有没有办法仍旧采用以前的方法来做COUNT(*)统计呢。当然可以了,我们可以强制指定普通索引,不过还需要加上WHERE条件,否则还是不行。后来搜了下,发现这是个bug,印风(zhaiwx)已经报告给官方了,bug id:81854。
这次的SQL执行耗时和在5.6下的就基本一样了。

4、后记

5.7版本整体挺赞的,不过还是有不少地方需要完善,期待能更成熟起来。

参考

1. MySQL 5.7.2 Release Notes:http://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-2.html

2. Limits on InnoDB Tableshttp://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html



文章转自老叶茶馆公众号,原文链接: https://mp.weixin.qq.com/s/x74ix7k6eT583pR6iGyO6Q

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
Linux PHP
linux centos7 安装php7.4 实测 遇到的坑
linux centos7 安装php7.4 实测 遇到的坑
1197 0
|
12月前
|
存储 人工智能 运维
《从流程适配到合规校验:AI赋能智能工单5天交付全流程》
本文复盘团队借AI工具协作开发企业级智能工单系统的实战:面对需适配12部门流程、三级权限管控、符合等保三级标准的需求,及核心开发抽调、10天需求仅余5天的困局,团队以Copilot Enterprise、CodeLlama、AI Code Reviewer构建协作体系。AI在选型阶段提供混合流程引擎方案,开发环节拆解逻辑、生成合规代码,优化时定位规则冲突与性能瓶颈,测试交付阶段生成用例与合规报告,最终5天完成交付,效率提升2倍。
509 2
|
数据采集 DataWorks 大数据
DataWorks
DataWorks
1766 5
|
机器学习/深度学习 自然语言处理 数据处理
通过深度学习识别情绪
通过深度学习识别情绪(Emotion Recognition using Deep Learning)是一项结合多模态数据的技术,旨在通过分析人类的面部表情、语音语调、文本内容等特征来自动识别情绪状态。情绪识别在人机交互、健康监测、教育、娱乐等领域具有广泛的应用。
2088 6
|
Java Android开发 Spring
idea开发常用快捷键总结
idea开发常用快捷键总结
784 9
|
Java 测试技术 Spring
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
这篇文章介绍了Spring Boot中配置文件的语法、如何读取配置文件以及如何通过静态工具类读取配置文件。
1588 0
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
|
缓存 Java API
API接口性能优化管理
在数字化时代,API性能优化对于提升软件效率和用户体验至关重要。本文介绍了多种优化方法:配置优化包括调整JVM参数等;代码层面减少重复调用并批量操作数据库;池化技术如线程池和HTTP连接池能有效利用资源;数据库优化通过索引提高查询速度;异步处理则使主流程业务不受阻塞;缓存策略如Redis缓存减少数据库访问;可观测性工具如日志平台和APM帮助监控性能。综合运用这些方法,可根据业务需求持续调整优化,显著提升API性能及用户体验。
|
安全 Java Spring
Spring Security整合JWT
该文档介绍了Spring Security与JWT的整合应用。在前后端分离的项目中,为了解决权限问题,通常采用Spring Security结合JWT的方案。文档涵盖了认证流程,包括同步认证和前后端分离认证,并详细说明了认证实现步骤,如环境准备、所需依赖(包括JWT库和Hutool工具包)的添加。此外,还提到从先前项目复制代码和配置以简化环境搭建。
586 6
|
Go 开发者
深入理解Go语言中的赋值与短声明
【8月更文挑战第31天】
470 0
|
缓存 IDE 开发工具
Arduino快速上手esp8266方案开发
Arduino快速上手esp8266方案开发
1092 0