在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: 1select_type: SIMPLE
        table: NULLpartitions: 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: 1select_type: SIMPLE
        table: sbtest1partitions: 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

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

MySQL · 引擎特性 · InnoDB COUNT(*) 优化(?)相关推荐

  1. MySQL · 引擎特性 · InnoDB 崩溃恢复过程

    在前面两期月报中,我们详细介绍了 InnoDB redo log 和 undo log 的相关知识,本文将介绍 InnoDB 在崩溃恢复时的主要流程. 本文代码分析基于 MySQL 5.7.7-RC ...

  2. MySQL · 引擎特性 · InnoDB 事务子系统介绍

    前言 在前面几期关于InnoDB Redo和Undo实现的铺垫后,本节我们从上层的角度来阐述InnoDB的事务子系统是如何实现的,涉及的内容包括:InnoDB的事务相关模块,如何实现MVCC及ACID ...

  3. MySQL · 引擎特性 · InnoDB 事务系统

    MySQL · 引擎特性 · InnoDB 事务系统 前言 关系型数据库的事务机制因其有原子性,一致性等优秀特性深受开发者喜爱,类似的思想已经被应用到很多其他系统上,例如文件系统等.本文主要介绍Inn ...

  4. MySQL 引擎特性 · InnoDB Buffer Pool

    前言 用户对数据库的最基本要求就是能高效的读取和存储数据,但是读写数据都涉及到与低速的设备交互,为了弥补两者之间的速度差异,所有数据库都有缓存池,用来管理相应的数据页,提高数据库的效率,当然也因为引入 ...

  5. MySQL · 引擎特性 · InnoDB Adaptive hash index介绍

    一 序 先看官网上的介绍(翻译来自MK提丰 ) The adaptive hash index (AHI) lets InnoDB perform more like an in-memory dat ...

  6. MySQL · 引擎分析 · InnoDB行锁分析

    前言 理解InnoDB行锁,分析一条SQL语句会加什么样的行锁,会锁住哪些数据范围对业务SQL设计和分析线上死锁问题都会有很大帮助.对于InnoDB的行锁,已经有多篇月报进行了介绍,这里笔者借鉴前面月 ...

  7. MySQL引擎特性GIS-R-TREE

    MySQL引擎特性GIS-R-TREE Geohash用于代表位置的经纬度编码成一个字符串,支持WGS 84 Coordinate System MySQL支持的空间数据类型包括GEOMETRY,PO ...

  8. MySQL引擎:InnoDB VS MyISAM

    文章目录 InnoDB特点 VS MyISAM特点 InnoDB存储引擎: MyISAM存储引擎: InnoDB索引 VS MyISAM索引 InnoDB索引: MyISAM索引: InnoDB特点 ...

  9. mysql using mrr_MySQL InnoDB MRR优化指南

    前言 MRR 是 Multi-Range Read 的简写,目的是减少磁盘随机访问,将随机访问转化为较为顺序的访问.适用于 range/ref/eq_ref 类型的查询. 实现原理: 1.在二级索引查 ...

最新文章

  1. uv_timer_t的释放问题
  2. 解决Qt Creator下 undefined reference to ‘qmain(int,char**)‘的问题
  3. 通过poi操作ppt中的图片
  4. 【python 3.6】python读取json数据存入MySQL(一)
  5. window.showModalDialog介绍
  6. 浙江省计算机vb二级考试题库,浙江省计算机二级vb上机试题题库..doc
  7. [转]编译器选项(摘自MSDN)及VC项目配置基础
  8. cocos2d(背景图片循环滚动)
  9. 2. 通用基础技术框架搭建
  10. CF1399C Boats Competition
  11. SIT测试和UAT测试
  12. sql plus能登录 plsqldev 登录提示 无法解析指定的连接标识符/PLSQL Developer的安装目录不能带括号/win10安装Oracle PLSQL Developer不能登录
  13. 解决Nextcloud新建用户默认语言是英文且默认地区是美国的方法
  14. GitHub绑定阿里云域名
  15. linux中使用rpm命令详解
  16. [转]电烙铁的使用小技巧
  17. 真正的IT技术男是什么样的
  18. .Net4.0 任务(Task)
  19. 【Java】第8章_InnerClass_Exception 上机实践与习题
  20. (筆記) 如何使用Debussy與ModelSim做Co-Simulation? (SOC) (Verilog) (VHDL) (Debussy) (ModelSim)

热门文章

  1. FTP搭建网络yum源
  2. 奥西300工程机服务器装系统,奥西工程机ftp服务器登录
  3. C++手册_迅为干货 | C程序调用shell
  4. nacative mysql_MySQL索引优化
  5. java script jquery_Java Script 学习笔记 -- jQuery
  6. java中接口什么时候用_我什么时候应该在java中使用接口?
  7. 华为交换机SSH和telnet登录配置
  8. Zabbix实战之客户端自动发现
  9. Hadoop详解(二):HDFS存储系统设计原理
  10. 计算机硬件大型作业报告,计算机硬件技术大作业报告.doc