MySQL 的执行原理(三)

5.4. InnoDB 中的统计数据

我们前边唠叨查询成本的时候经常用到一些统计数据,比如通过 SHOW
TABLE STATUS 可以看到关于表的统计数据,通过 SHOW INDEX 可以看到关于索引
的统计数据,那么这些统计数据是怎么来的呢?它们是以什么方式收集的呢?

5.4.1. 统计数据存储方式

InnoDB 提供了两种存储统计数据的方式:
永久性的统计数据,这种统计数据存储在磁盘上,也就是服务器重启之后这些统计数据还在。
非永久性的统计数据,这种统计数据存储在内存中,当服务器关闭时这些这些统计数据就都被清除掉了,等到服务器重启之后,在某些适当的场景下才会重新收集这些统计数据。
MySQL 给我们提供了系统变量 innodb_stats_persistent 来控制到底采用哪种方式去存储统计数据。在 MySQL 5.6.6 之前,innodb_stats_persistent 的值默认是OFF,也就是说 InnoDB 的统计数据默认是存储到内存的,之后的版本中 innodb_stats_persistent 的值默认是 ON,也就是统计数据默认被存储到磁盘中。

SHOW VARIABLES LIKE 'innodb_stats_persistent';

在这里插入图片描述
不过最近的 MySQL 版本都基本不用基于内存的非永久性统计数据了,所以我们也就不深入研究。
不过 InnoDB 默认是以表为单位来收集和存储统计数据的,也就是说我们可以把某些表的统计数据(以及该表的索引统计数据)存储在磁盘上,把另一些表的统计数据存储在内存中。怎么做到的呢?我们可以在创建和修改表的时候通过指定 STATS_PERSISTENT 属性来指明该表的统计数据存储方式:

CREATE TABLE 表名 (...) Engine=InnoDB, STATS_PERSISTENT = (1|0);
ALTER TABLE 表名 Engine=InnoDB, STATS_PERSISTENT = (1|0);

当 STATS_PERSISTENT=1 时,表明我们想把该表的统计数据永久的存储到磁盘上,当 STATS_PERSISTENT=0 时,表明我们想把该表的统计数据临时的存储到内存中。如果我们在创建表时未指定 STATS_PERSISTENT 属性,那默认采用系统变量 innodb_stats_persistent 的值作为该属性的值。

5.4.2. 基于磁盘的永久性统计数据

当我们选择把某个表以及该表索引的统计数据存放到磁盘上时,实际上是把这些统计数据存储到了两个表里:

SHOW TABLES FROM mysql LIKE 'innodb%';

在这里插入图片描述
可以看到,这两个表都位于 mysql 系统数据库下边,其中:
innodb_table_stats 存储了关于表的统计数据,每一条记录对应着一个表的统计数据。
innodb_index_stats 存储了关于索引的统计数据,每一条记录对应着一个索引的一个统计项的统计数据。

5.4.2.1. innodb_table_stats

直接看一下这个 innodb_table_stats 表中的各个列都是干嘛的:
在这里插入图片描述
database_name 数据库名
table_name表名
last_update 本条记录最后更新时间
n_rows 表中记录的条数
clustered_index_size 表的聚簇索引占用的页面数量
sum_of_other_index_sizes 表的其他索引占用的页面数量
我们直接看一下这个表里的内容:

SELECT * FROM mysql.innodb_table_stats;

在这里插入图片描述
几个重要统计信息项的值如下:

  • n_rows 的值是 10350,表明 order_exp 表中大约有 10350 条记录,注意这个数据是估计值。
  • clustered_index_size 的值是 97,表明 order_exp 表的聚簇索引占用 97 个页面,这个值是也是一个估计值。
  • sum_of_other_index_sizes 的值是 81,表明 order_exp 表的其他索引一共占用81 个页面,这个值是也是一个估计值。
    n_rows 统计项的收集
    InnoDB 统计一个表中有多少行记录是这样的:
    按照一定算法(并不是纯粹随机的)选取几个叶子节点页面,计算每个页面中主键值记录数量,然后计算平均一个页面中主键值的记录数量乘以全部叶子节点的数量就算是该表的 n_rows 值。

可以看出来这个 n_rows 值精确与否取决于统计时采样的页面数量,MySQL用名为 innodb_stats_persistent_sample_pages 的系统变量来控制使用永久性的统计数据时,计算统计数据时采样的页面数量。该值设置的越大,统计出的 n_rows值越精确,但是统计耗时也就最久;该值设置的越小,统计出的 n_rows 值越不精确,但是统计耗时特别少。所以在实际使用是需要我们去权衡利弊,该系统变量的默认值是 20。
InnoDB 默认是以表为单位来收集和存储统计数据的,我们也可以单独设置某个表的采样页面的数量,设置方式就是在创建或修改表的时候通过指定STATS_SAMPLE_PAGES 属性来指明该表的统计数据存储方式.

CREATE TABLE 表名 (…) Engine=InnoDB, STATS_SAMPLE_PAGES = 具体的采样页面数量;
ALTER TABLE 表名 Engine=InnoDB, STATS_SAMPLE_PAGES = 具体的采样页面数量;
如果我们在创建表的语句中并没有指定 STATS_SAMPLE_PAGES 属性的话,将默认使用系统变量 innodb_stats_persistent_sample_pages 的值作为该属性的值。
clustered_index_size 和 sum_of_other_index_sizes 统计项的收集牵涉到很具体的 InnoDB 表空间的知识和存储页面数据的细节,我们就不深入讲解了。

5.4.2.2. innodb_index_stats

直接看一下这个 innodb_index_stats 表中的各个列都是干嘛的:

desc mysql.innodb_index_stats;

在这里插入图片描述
字段名 描述
database_name 数据库名
table_name表名
index_name 索引名
last_update 本条记录最后更新时间
stat_name 统计项的名称
stat_value 对应的统计项的值
sample_size为生成统计数据而采样的页面数量
stat_description对应的统计项的描述
innodb_index_stats 表的每条记录代表着一个索引的一个统计项。可能这会 大家有些懵逼这个统计项到底指什么,别着急,我们直接看一下关于 order_exp 表的索引统计数据都有些什么:

mysql> SELECT * FROM mysql.innodb_index_stats WHERE table_name =
'order_exp';

在这里插入图片描述
先查看 index_name 列,这个列说明该记录是哪个索引的统计信息,从结果中我们可以看出来,PRIMARY 索引(也就是主键)占了 3 条记录,idx_expire_time 索引占了 6 条记录。
针对 index_name 列相同的记录,stat_name 表示针对该索引的统计项名称,stat_value 展示的是该索引在该统计项上的值,stat_description 指的是来描述该 统计项的含义的。我们来具体看一下一个索引都有哪些统计项:

  • n_leaf_pages:表示该索引的叶子节点占用多少页面。
  • size:表示该索引共占用多少页面。
  • n_diff_pfxNN:表示对应的索引列不重复的值有多少。其中的 NN 长得有点儿怪呀,啥意思呢?

其实 NN 可以被替换为 01、02、03… 这样的数字。比如对于 u_idx_day_status来说:
n_diff_pfx01 表示的是统计 insert_time 这单单一个列不重复的值有多少。
n_diff_pfx02 表示的是统计 insert_time,order_status 这两个列组合起来不重复的值有多少。
n_diff_pfx03 表示的是统计 insert_time,order_status,expire_time 这三个列组合起来不重复的值有多少。
n_diff_pfx04 表示的是统计 key_pare1、key_pare2、expire_time、id 这四个列组合起来不重复的值有多少。
对于普通的二级索引,并不能保证它的索引列值是唯一的,比如对于
idx_order_no 来说,key1 列就可能有很多值重复的记录。此时只有在索引列上加上主键值才可以区分两条索引列值都一样的二级索引记录。
对于主键和唯一二级索引则没有这个问题,它们本身就可以保证索引列值的不重复,所以也不需要再统计一遍在索引列后加上主键值的不重复值有多少。比如 u_idx_day_statu 和 idx_order_no。
在计算某些索引列中包含多少不重复值时,需要对一些叶子节点页面进行采样,sample_size 列就表明了采样的页面数量是多少。
对于有多个列的联合索引来说,采样的页面数量是:
innodb_stats_persistent_sample_pages × 索引列的个数。
在这里插入图片描述
当需要采样的页面数量大于该索引的叶子节点数量的话,就直接采用全表扫描来统计索引列的不重复值数量了。所以大家可以在查询结果中看到不同索引对应的 size 列的值可能是不同的。

5.4.2.3. 定期更新统计数据

随着我们不断的对表进行增删改操作,表中的数据也一直在变化,
innodb_table_stats 和 innodb_index_stats 表里的统计数据也在变化。MySQL 提供了如下两种更新统计数据的方式:
开启 innodb_stats_auto_recalc
系统变量 innodb_stats_auto_recalc 决定着服务器是否自动重新计算统计数据,它的默认值是 ON,也就是该功能默认是开启的。每个表都维护了一个变量, 该变量记录着对该表进行增删改的记录条数,如果发生变动的记录数量超过了表 大小的 10%,并且自动重新计算统计数据的功能是打开的,那么服务器会重新进行一次统计数据的计算,并且更新 innodb_table_stats 和 innodb_index_stats 表。
不过自动重新计算统计数据的过程是异步发生的,也就是即使表中变动的记录数超过了 10%,自动重新计算统计数据也不会立即发生,可能会延迟几秒才会进行计算。

再一次强调,InnoDB 默认是以表为单位来收集和存储统计数据的,我们也可以单独为某个表设置是否自动重新计算统计数的属性,设置方式就是在创建或修改表的时候通过指定 STATS_AUTO_RECALC 属性来指明该表的统计数据存储方式:

CREATE TABLE 表名 (...) Engine=InnoDB, STATS_AUTO_RECALC = (1|0);
ALTER TABLE 表名 Engine=InnoDB, STATS_AUTO_RECALC = (1|0);

当 STATS_AUTO_RECALC=1 时,表明我们想让该表自动重新计算统计数据,
当 STATS_AUTO_RECALC=0 时,表明不想让该表自动重新计算统计数据。如果我们在创建表时未指定 STATS_AUTO_RECALC 属性,那默认采用系统变量 innodb_stats_auto_recalc 的值作为该属性的值。
手动调用 ANALYZE TABLE 语句来更新统计信息
如果 innodb_stats_auto_recalc 系统变量的值为 OFF 的话,我们也可以手动调用 ANALYZE TABLE 语句来重新计算统计数据,比如我们可以这样更新关于 order_exp 表的统计数据:

mysql> ANALYZE TABLE order_exp;

在这里插入图片描述
ANALYZE TABLE 语句会立即重新计算统计数据,也就是这个过程是同步的,在表中索引多或者采样页面特别多时这个过程可能会特别慢最好在业务不是很繁忙 的时候再运行。

5.4.2.4. 手动更新 innodb_table_stats 和 innodb_index_stats 表

其实 innodb_table_stats 和 innodb_index_stats 表就相当于一个普通的表一样,我们能对它们做增删改查操作。这也就意味着我们可以手动更新某个表或者索引的统计数据。比如说我们想把 order_exp 表关于行数的统计数据更改一下可以这么做:
步骤一:更新 innodb_table_stats 表。
步骤二:让 MySQL 查询优化器重新加载我们更改过的数据。
更新完 innodb_table_stats 只是单纯的修改了一个表的数据,需要让 MySQL.

查询优化器重新加载我们更改过的数据,运行下边的命令就可以了:
FLUSH TABLE order_exp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git下载安装配置及Git在Gitee上拉取和上传代码教程

一、Git下载安装和配置 Git是一个分布式版本控制系统,用于跟踪文件的变化并协作开发。以下是安装和配置Git的简单步骤: 安装Git 下载Git安装程序:Git下载地址。 运行安装程序,按照提示进行安装。 在安装过程中,选择…

Notepad++ 和正则表达式 只保留自己想要的内容

一、需求 如下文本,三段相同结构的数据,想要获取每段结构中‘重复的Ids ’后面的数字 2023-10-26 18:49:49 重复的Ids 26443,26575 要删除的Ids 4174,4199,4200,55502023-10-26 18:49:49 重复的Ids 26436,26443,26575 要删除的Ids 4166,4199,4200,5550…

特殊文件(XML文件)

一&#xff0c;XML文件概括 二&#xff0c;案例 <?xml version"1.0" encoding"UTF-8" ?> <!--注释&#xff1a;以上抬头声明必须写在第一不然报错--> <users><user id"1"><uame>张无忌</uame><性别&g…

bson数据通过BulkOperations批量入库mongo表报重复ID处理

bson数据批量入库mongo表报重复ID处理 一、需求 需要将一批bson格式数据批量入库指定mongo表&#xff0c;并且该表已存在数据&#xff0c;批量入库的数据可能和表中已有数据重复。 二、批量入库时的问题 采用MongoTemplate 原生的BulkOperations批量操作API upsert方法进行…

STM32:OLED屏幕开发

一、OLED原理 所谓的屏幕就是由一个个小灯组成&#xff0c;每个小灯称之为一个像素。只要在屏幕上有选择地点亮一部分小灯&#xff0c;就可以显示我们想要的图案。所谓下分辨率就是屏幕上的小灯数量。常见单片机中常见的屏幕分辨率常见的就是128(列长)*64(行高)。如果每个小灯都…

【云栖 2023】张治国:MaxCompute 架构升级及开放性解读

云布道师 本文根据 2023 云栖大会演讲实录整理而成&#xff0c;演讲信息如下 演讲人&#xff1a;张治国|阿里云智能计算平台研究员、阿里云 MaxCompute 负责人 演讲主题&#xff1a;MaxCompute架构升级及开放性解读 活动&#xff1a;2023云栖大会 MaxCompute 发展经历了三个阶…

发币成功,记录一下~

N年前就听说了这样一种说法——“一个熟练的区块链工程师&#xff0c;10分钟就可以发出一个新的币” 以前仅仅是有这么一个认识&#xff0c;但当时并不特别关注这个领域。 最近系统性学习中&#xff0c;今天尝试发币成功啦&#xff0c;记录一下&#xff5e; 发在 Sepolia Tes…

Minikube Mac安装使用

minikube start | minikube 安装minikube curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 sudo install minikube-darwin-amd64 /usr/local/bin/minikube 1 2 启动本地集群 minikube start --driverdocker # 等待几分钟 让docker 拉…

分布式锁实现对比

1、对比 tairzookeper性能高 低可靠性低 高 2、zookeper实现分布式锁 特点&#xff1a; Zookeeper能保证数据的强一致性&#xff0c;用户任何时候都可以相信集群中每个节点的数据都是相同的。 加锁 客户端在ZooKeeper一个特定的节点下创建临时顺序节点&…

kerberos-MS14-068(kerberos域用户提权)

点击星标&#xff0c;即时接收最新推文 微软官方在2014年11月18日发布了一个紧急补丁&#xff0c;Windows全版本服务器系统受到影响&#xff0c;包括Windows Server 2003&#xff0c;Windows Server 2008&#xff0c;Windows Server 2008 R2&#xff0c;Windows Server 2012和W…

【ROS】RViz2源码分析(三):核心类VisualizerApp

【ROS】郭老二博文之:ROS目录 1、简述 VisualizerApp包含了三个主要的功能: QApplication:程序中主要调用app_->processEvents()来处理刷新界面,处理闪屏VisualizationFrame:窗口类都在此;RosClientAbstractionIface包含rclcpp::Node:代表ROS节点2、VisualizationF…

LeetCode热题100——二分查找

二分查找 1. 搜索插入位置2. 搜素二维矩阵3. 在排序数组中查找第一个和最后一个元素位置 1. 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 // 题…

【电路笔记】-星三角变换(Star-Delta Transformation)

星三角变换&#xff08;Star-Delta Transformation&#xff09; 文章目录 星三角变换&#xff08;Star-Delta Transformation&#xff09;1、概述1.1 单相配置1.2 多相配置 2、三相连接2.1 Y配置2.2 Δ配置 3、Y-Δ 和 Δ-Y 变换3.1 Y-Δ变换3.2 Δ-Y变换3.3 应用 4、总结 本文…

蓝桥杯每日一题2023.11.20

题目描述 “蓝桥杯”练习系统 (lanqiao.cn) 题目分析 方法一&#xff1a;暴力枚举&#xff0c;如果说数字不在正确的位置上也就意味着这个数必须要改变&#xff0c;进行改变记录即可 #include<bits/stdc.h> using namespace std; const int N 2e5 10; int n, a[N], …

在springBoot中同时使用mysql和MongoDB

在SpringBoot中非关系向数据库MongoDB和关系型数据库MySQL都可通过引入相关依赖并按照指定配置单独集成; mysql引入依赖: compile "org.springframework.boot:spring-boot-starter-web:1.5.18.RELEASE"compile "org.springframework.boot:spring-boot-start…

Java将List转换为Tree数据

思路 我们首先要知道数据中&#xff0c;哪两列能够体现父子级我们需要找到最顶层父 id 是什么&#xff0c;因为只有知道最顶层的父 id&#xff0c;我们才能进行递归我们要在不改变数据的原有结构下&#xff0c;而转换为 Tree 结构&#xff0c;那么就需要创建新的结构 代码 /…

【活动通知】2023 Elastic Meetup 北京站将于12月2日下午1点30在北京召开

《2023 Elastic Meetup 北京站》活动将于 12 月 2 日下午 1 点 30 在北京市海淀区西北旺东路10号腾讯北京总部大楼213会议室举办&#xff0c;届时将有行业专家及知名企业分享他们在 Elasticsearch 应用中的经验与观点&#xff0c;带来最前沿的技术分享与思想碰撞。 请使用电脑浏…

C++标准模板库(STL)-set介绍

在C中&#xff0c;set是一种容器&#xff0c;它包含了唯一元素的有序集合。set库提供了一系列的类模板&#xff0c;用于创建和操作集合。 set基本操作 insert()&#xff1a;此操作用于将元素插入到set中。调用insert()函数&#xff0c;并传入需要插入的元素即可。例如&#x…

车载毫米波雷达行业发展5——企业

5.1 博世 5.1.1 公司简介 博世集团创立于 1886 年&#xff0c;业务涵盖汽车与智能交通技术、工业技术、消费品、能源与建 筑技术四大领域&#xff0c;是德国最大的工业企业之一、全球最大的汽车零部件供应商、最早研究车载毫米波雷达的企业之一。博世在高级辅助驾驶和自动驾驶…

移动语义和完美转发

移动语义和完美转发 移动语义 移动语义是 C11 引入的一项特性&#xff0c;通过右值引用&#xff08;Rvalue Reference&#xff09;实现。它的目标是提高对于临时对象或即将销毁的对象的效率&#xff0c;避免不必要的深拷贝&#xff0c;而是在必要的时候将资源所有权从一个对象…