MySQL · 引擎特性 · InnoDB COUNT(*) 优化(?)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
PolarClaw,2核4GB
简介:

在5.7版本中,InnoDB实现了新的handler的records接口函数,当你需要表上的精确记录个数时,会直接调用该函数进行计算。

使用

实际上records接口函数是在优化阶段调用的,在满足一定条件时,直接去计算行级计数。其explain出来的结果相比老版本也有所不同,这里我们使用sysbench的sbtest表来进行测试,共200万行数据。

mysql> show create table sbtest1\G
*************************** 1. row ***************************
       Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `k` int(10) unsigned NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=2000001 DEFAULT CHARSET=utf8 MAX_ROWS=1000000
1 row in set (0.00 sec)

mysql> explain select count(*) from sbtest1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: NULL
   partitions: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
     filtered: NULL
        Extra: Select tables optimized away
1 row in set, 1 warning (0.00 sec)

注意这里Extra里为”Select tables optimized away”,表示在优化器阶段已经被优化掉了。如果给id列带上条件的话,则回退到之前的逻辑

mysql> explain select count(*) from sbtest1 where id > 0\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: sbtest1
   partitions: NULL
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 960984
     filtered: 100.00
        Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)

实现

WL#6742中,为InnoDB实现了handler的records函数接口

函数栈

opt_sum_query
|--> get_exact_record_count
	|--> ha_records
		|--> ha_innobase::records
			|-->row_scan_index_for_mysql
  • HA_HAS_RECORDS:引擎flag,表示是否可以把count(*)下推到引擎层
  • 总是使用聚集索引来进行计算行数
  • 只需要读取主键值,无需去读取外部存储列(row_prebuilt_t::read_just_key),如果行记录较大的话,就可以节省客观的诸如内存拷贝之类的操作开销
  • 计算过程可中断,每检索1000条记录,检查事务是否被中断
  • 由于只有一次引擎层的调用,减少了Server层和InnoDB的交互,避免了无谓的内存操作或格式转换
  • 对于分区表,在5.7版本已经下推到innodb层,因此分区表的计算方式(ha_innopart::records)是针对每个分区调用ha_innobase::records,再将结果累加起来

相关代码:
commit1
commit2

缺点

由于总是强制使用聚集索引,缺点很明显:当二级索引的大小远小于聚集索引,且数据不在内存中时,使用二级索引显然要快些,因此文件IO更少。如下例:

默认情况下检索所有行(以下测试都是在清空buffer pool时进行的):

mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
|  2000000 |
+----------+
1 row in set (3.92 sec)

即时强制指定索引也没用 :(

mysql> select count(*) from sbtest1 force index(k_1);
+----------+
| count(*) |
+----------+
|  2000000 |
+----------+
1 row in set (3.86 sec)

但如果带上一个简单的条件,让select count(*)走索引k_1,耗费的时间立马下降了….

mysql> select count(*) from sbtest1 where k > 0;
+----------+
| count(*) |
+----------+
|  2000000 |
+----------+
1 row in set (1.05 sec)

个人认为这算是一个性能退化,退一步讲,如果用户知道force index能够走一个更好的索引来计算行数,优化器应该做出选择,而不是总是无条件选择聚集索引,提了个Bug到官方

其他

WL#6742还提到了一个尚未公布的WL#6605,从其只言片语中可以推断官方有意向实现即时获得行数:

The next worklog, WL#6605, is intended to return the COUNT(*) through this handler::records() interface almost immediately in all conditions just by keeping track if the base committed count along with transaction deltas

让我们继续对新版本保持期待吧 :)

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
7月前
|
SQL 存储 关系型数据库
MySQL内存引擎:Memory存储引擎的适用场景
MySQL Memory存储引擎将数据存储在内存中,提供极速读写性能,适用于会话存储、临时数据处理、高速缓存和实时统计等场景。但其数据在服务器重启后会丢失,不适合持久化存储、大容量数据及高并发写入场景。本文深入解析其特性、原理、适用场景与限制,并提供性能优化技巧及替代方案比较,助你合理利用这一“内存闪电”。
|
7月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1247 152
|
7月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
924 156
|
7月前
|
存储 关系型数据库 MySQL
介绍MySQL的InnoDB引擎特性
总结而言 , Inno DB 引搞 是 MySQL 中 高 性 能 , 高 可靠 的 存 储选项 , 宽泛 应用于要求强 复杂交易处理场景 。
297 15
|
7月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
8月前
|
缓存 关系型数据库 MySQL
降低MySQL高CPU使用率的优化策略。
通过上述方法不断地迭代改进,在实际操作中需要根据具体场景做出相对合理判断。每一步改进都需谨慎评估其变动可能导致其他方面问题,在做任何变动前建议先在测试环境验证其效果后再部署到生产环境中去。
330 6
|
12月前
|
存储 网络协议 关系型数据库
MySQL8.4创建keyring给InnoDB表进行静态数据加密
MySQL8.4创建keyring给InnoDB表进行静态数据加密
460 1
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
2277 57
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
12月前
|
SQL 缓存 关系型数据库
使用温InnoDB缓冲池启动MySQL测试
使用温InnoDB缓冲池启动MySQL测试
229 0
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
436 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多
    下一篇
    开通oss服务