innoDB数据收集方式—永久性&非永久性(四十三)

2023-10-29

上篇文章说了连接查询的成本,主要由驱动表的扇出值和被驱动表的查询方法决定,而成本这些都是可以在%cost%表查看的,因为分为server和engine表,server不管理数据成本,里面包含连接管理,查询缓存,sql解码,sql优化,engine就是数据引擎成本,而distinct,union等特殊查询,会建立临时表,临时表看数据量可能建立磁盘或者内存,比如distinct会用unique索引建立临时表去重。

连接查询成本(2)---mysql进阶(四十二)

我们前面说了show index from可以看到表的索引信息,show table status可以看到表的数据,那这些数据怎么来的呢?分为两种不同的统计数据方式。

两种不同的统计数据存储方式

innoDB_stats_persistent字段,在mysql5.6.6之前是OFF,代表默认吧统计数据存储在内存中,在之后是on,默认吧数据存储在磁盘上。

innoDB默认以表为单位存储数据,所以在建立表的时候我们可以指定存储在磁盘还是存储在内存,当指定为stats_persistent为1时,代表永久性存储,当stats_persistent为0时,为内存存储。当没有指定的时候,默认用innoDB_stats_persistent值。

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

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

永久性统计:

表示统计数据存储在磁盘上,服务器重启之后这些数据还在。

我们可以查询数据库:

mysql> show tables from mysql like 'innodb%';
+---------------------------+
| Tables_in_mysql (innodb%) |
+---------------------------+
| innodb_index_stats        |
| innodb_table_stats        |
+---------------------------+
2 rows in set (0.00 sec)

可以看到这两个表都位于系统数据库下面,

innoDB_table_stats:代表着每个表的统计数据,每一条记录对应着一个表的统计数据。

innoDB_index_stats:存着索引的统计数据,每一条记录对应着一个索引的统计数据。

innodb_table_stats表

我们先把表里数据查询出来分析:

mysql> SELECT * FROM mysql.innodb_table_stats;
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name    | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| mysql         | gtid_executed | 2018-07-10 23:51:36 |      0 |                    1 |                        0 |
| sys           | sys_config    | 2018-07-10 23:51:38 |      5 |                    1 |                        0 |
| mac           | single_table  | 2018-12-10 17:03:13 |   9693 |                   97 |                      175 |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
3 rows in set (0.01 sec)

database_name:代表数据库名称。

table_name:表名称。

last_update:表最后更新时间。

n_rows:表里存在的数据。

clustered_index_size:聚簇索引占的页。

sum_of_other_index_sizes:其他索引占的页。

我们可以看到熟悉的single_table表数据是9636条,聚簇索引占的页面时97,其他索引占的页面时175,这些都是估值。

n_rows数据的收集:

按照一定的算法,随机选几个叶子节点的数据,然后算一个叶子节点数据平均值,再把平均值乘以总叶子数。所以算出来的是一个估值,innodb索引设置了一个系统参数innodb_states_persistent_simple_page,默认是20,当这个值设置的越大,计算的越精确,但耗时也就越长了,当这个值越小,就计算的偏离更大,但速度也会快很多。

前面说过innoDB是以表为单位来收集和统计数据的,所以也可以设置,不设置就是取innodb_states_persistent_simple_page的默认值

CREATE TABLE 表名 (...) Engine=InnoDB, STATS_SAMPLE_PAGES = 具体的采样页面数量;

ALTER TABLE 表名 Engine=InnoDB, STATS_SAMPLE_PAGES = 具体的采样页面数量;

clustered_index_size 和 sum_of_other_index_sizes

这里会用到innoDB表空间的知识,如果大家仔细看了前面的文章,下面是可以看懂的,否则建议停止。

1、先从字典表sys_indexes查询各个索引根页面信息。

2、从根页面的page header找到对应的segment header,有两个字段:page_btr_seg_leaf:b+树叶子段对应的segment header,page_btr_seg_top:b+树非叶子段对应的segment header。

3、从叶子段和非叶子段找到两个inode entry

4、inode entry里面有三个链表,free,not_full,full。从三个链表读出list lenth占用区的大小,然后每个区有64个页,就知道有多少个页。

5、聚簇索引b+树吧叶子节点和非叶子节点里的页加起来就是clustered_inde_size,同理其他索引这样加起来获取的就是sum_of_other_sizes。

注意:前面说过满32个页面,才会吧区划分到某个段区,否则这个区就是碎片区,所以上面计算的值可能比真实聚簇索引和非聚簇索引占用的页面数要多。

innoDB_index_stats:

先把表查询来看看:

mysql> SELECT * FROM mysql.innodb_index_stats WHERE table_name = 'single_table';
+---------------+--------------+--------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name   | index_name   | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+--------------+--------------+---------------------+--------------+------------+-------------+-----------------------------------+
| xiaohaizi     | single_table | PRIMARY      | 2018-12-14 14:24:46 | n_diff_pfx01 |       9693 |          20 | id                                |
| xiaohaizi     | single_table | PRIMARY      | 2018-12-14 14:24:46 | n_leaf_pages |         91 |        NULL | Number of leaf pages in the index |
| xiaohaizi     | single_table | PRIMARY      | 2018-12-14 14:24:46 | size         |         97 |        NULL | Number of pages in the index      |
| xiaohaizi     | single_table | idx_key1     | 2018-12-14 14:24:46 | n_diff_pfx01 |        968 |          28 | key1                              |
| xiaohaizi     | single_table | idx_key1     | 2018-12-14 14:24:46 | n_diff_pfx02 |      10000 |          28 | key1,id                           |
| xiaohaizi     | single_table | idx_key1     | 2018-12-14 14:24:46 | n_leaf_pages |         28 |        NULL | Number of leaf pages in the index |
| xiaohaizi     | single_table | idx_key1     | 2018-12-14 14:24:46 | size         |         29 |        NULL | Number of pages in the index      |
| xiaohaizi     | single_table | idx_key2     | 2018-12-14 14:24:46 | n_diff_pfx01 |      10000 |          16 | key2                              |
| xiaohaizi     | single_table | idx_key2     | 2018-12-14 14:24:46 | n_leaf_pages |         16 |        NULL | Number of leaf pages in the index |
| xiaohaizi     | single_table | idx_key2     | 2018-12-14 14:24:46 | size         |         17 |        NULL | Number of pages in the index      |
| xiaohaizi     | single_table | idx_key3     | 2018-12-14 14:24:46 | n_diff_pfx01 |        799 |          31 | key3                              |
| xiaohaizi     | single_table | idx_key3     | 2018-12-14 14:24:46 | n_diff_pfx02 |      10000 |          31 | key3,id                           |
| xiaohaizi     | single_table | idx_key3     | 2018-12-14 14:24:46 | n_leaf_pages |         31 |        NULL | Number of leaf pages in the index |
| xiaohaizi     | single_table | idx_key3     | 2018-12-14 14:24:46 | size         |         32 |        NULL | Number of pages in the index      |
| xiaohaizi     | single_table | idx_key_part | 2018-12-14 14:24:46 | n_diff_pfx01 |       9673 |          64 | key_part1                         |
| xiaohaizi     | single_table | idx_key_part | 2018-12-14 14:24:46 | n_diff_pfx02 |       9999 |          64 | key_part1,key_part2               |
| xiaohaizi     | single_table | idx_key_part | 2018-12-14 14:24:46 | n_diff_pfx03 |      10000 |          64 | key_part1,key_part2,key_part3     |
| xiaohaizi     | single_table | idx_key_part | 2018-12-14 14:24:46 | n_diff_pfx04 |      10000 |          64 | key_part1,key_part2,key_part3,id  |
| xiaohaizi     | single_table | idx_key_part | 2018-12-14 14:24:46 | n_leaf_pages |         64 |        NULL | Number of leaf pages in the index |
| xiaohaizi     | single_table | idx_key_part | 2018-12-14 14:24:46 | size         |         97 |        NULL | Number of pages in the index      |
+---------------+--------------+--------------+---------------------+--------------+------------+-------------+-----------------------------------+
20 rows in set (0.03 sec)

第一列是数据库名称。

第二列是表名。

index_name:索引名字。

stat_name:统计项名称。

stat_value:对应统计项值。

sample_size:为生成统计数据而采样的页面数据。

stat_descreption:对应的统计项描述。

注意这个表的主键是(database_name,table_name,index_name,stat_name),其中stat_name代表统计项名称,所以一个索引代表一个统计项,

Index_name:索引名字,primary主键有三条,idx_key_pary索引又6条。

Stat_name表示该索引统计项名称,stat_value表示该索引统计项的值:

N_leaf_pages:表示该索引叶子节点占用多少页面。

Size:表示该索引占用多少页面。

N_diff_pfxNN:表示索引对应不重复的值。比如n_diff_pfx01表示key_part1单个列不重复的值,比如n_diff_pfx02表示key_part1,key_part2两个列不重复的值。

在计算索引列有多少重复值时候,需要对叶子节点进行采样,sample_page就是采样的页面数量多少。

定期更新统计数据

随着我们不断的增删查改,统计数据肯定也是在变化的,mysql有两种更新统计数据的方法:

  1. 开启innodb_stats_auto_recalc:开启决定这服务器会自动计算统计数据,默认值是on,每个表维护着一个变量,当修改的数据大于表数据的百分之10,则会自动计算,更新innoDB_table_stats和innoDB_index_stats。这里是异步计算的,所以如果超过百分之10,可能有几秒钟延迟。
  2. 未开启:这时候如果innoDB_stats_auto_recalc是off的,我们可以手动运行

ANALYZE TABLE single_table;

这里计算是同步进行的,尽量不要用,用也选在业务空闲的时间段进行。

手动更新innoDB_table_stats和innoDB_index_stats

因为这两个都属于表,我们自己也可以手动更新他们的数据,修改表的字段之后,mysql优化器并没有加载他,还需要刷新一下,之后我们运行show table status就可以看到数据。

UPDATE innodb_table_stats 
    SET n_rows = 1
    WHERE table_name = 'single_table';

//刷新
flush table single_table;

非永久性统计:

存储在内存里,当服务器关闭就清除,当下次还需要的时候再重新统计。

我们吧系统变量innoDB_stats_persistent默认的on改为off,就是默认非永久性,或者创建表的时候指定stats_persistent为0,也表示非永久性。

与innodb_stats_persistent_sample_pages相比,这里控制采样数据数量的是innodb_stats_transient_sample_pages。因为mysql默认都是开启永久性统计,所以这个用的很少。

innoDB_stats_method的使用

我们知道索引不重复列的数量,这个对mysql优化很重要,他有两个使用场景:

  1. 单表查询区间太多:

SELECT * FROM tbl_name WHERE key IN ('xx1', 'xx2', ..., 'xxn');

当in里面的参数太多,采用index_drive访问b+树统计区间记录数量太耗性能,所以依赖统计数据的平均值来计算。

  1. 连接查询,如果涉及两个表等值匹配,连接条件的被驱动表又有索引时,则可以用ref访问被驱动表:

SELECT * FROM t1 JOIN t2 ON t1.column = t2.key WHERE ...;

在对t2表查询之前,t2.key的值是不确定的, 所以这时候只能依赖统计数据去计算平均值来判断记录数。

假设某个索引查询出来有多个null值怎么处理呢?

  1. 所有null为一样,所以不管查询出来几个null,都只显示唯一的一个null。
  2. 每个null都是唯一的。
  3. Null值不算唯一,忽略。

Mysql给这个设置了系统变量,innodb_stats_method,相当于这个null怎么定义可以用户自己决定,分别对应着

nulls_equals:null一样。

Nulls_unequals:null每个都不一样。

Nulls_ignored:null值忽略。

总结:innodb有两种存储统计数据的方式,永久性和非永久性,可以用innodb_stats_persistent控制,也可用个人创建表的时候控制,stats_persistent。永久性就是可以存在磁盘上,可以用innoDB_stats_persistent_sample_pages控制采集多少页面。非永久性可以用innoDB_Stats_transient_sample_pages控制采集多少页面。innoDB_stats_auto_recale控制是否自动计算统计数据。

Stats_sample_pages和stats_auto_recalc也可用在创建表的时候控制。

innoDb_stats_methods可以控制null值的对待。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

innoDB数据收集方式—永久性&非永久性(四十三) 的相关文章

  • sqlalchemy 中的随机 ID(pylon)

    我正在使用 pylons 和 sqlalchemy 我想知道如何将一些随机 id 作为primary key 最好的方法是使用随机生成的 UUID import uuid id uuid uuid4 uuid 数据类型在某些数据库中本机可用
  • mysql - 有什么方法可以帮助使用另一个索引进行全文搜索?

    假设我有一个 文章 表 其中包含以下列 article text fulltext indexed author id indexed 现在我想搜索特定作者撰写的文章中出现的术语 所以像这样 select from articles whe
  • SQL 语法检查器和验证器? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有类似 SQL 的 lint 语法检查器和验证器 之类的东西 有一个项目 SQLLint 检测 S
  • 是否有工具可以将 Neo4j 图转储为 Cypher 并从 Cypher 重新加载它?

    每个熟悉 MySQL 的人都可能使用过 mysqldump 命令 它可以生成代表 MySQL 数据库中的架构和数据的 SQL 语句文件 这些 SQL 文本文件通常用于多种用途 备份 播种副本 在安装之间复制数据库 将产品数据库复制到临时环境
  • 如何获取共同好友列表

    你好 我想知道如何才能找到共同的朋友 我目前在思考这个问题时遇到问题 我有一个名为 users 的表 它是这样的 id name 1 Kenny 2 Jack 3 Jimmy 4 Chris 5 Meg 6 Jake 7 Micheal 8
  • 如何在存储过程中使用名称求和和分组?

    我想对钱列求和 但我想要状态中的组名称和代码 这是存储过程代码 Sql Server 2008 SELECT um upmoney as money um pId as code um FName as name up status as
  • 哈希 MySQL 数据库架构

    我想对 MySQL 数据库模式 没有数据 进行哈希 签名 以便对其进行校验和 以确保它不被其他人修改 我怎样才能实现它 据我了解您的问题 您需要表校验和 checksum table table 所以 我想 只需对空表进行校验和
  • 方法“Boolean Contains(System.String)”不支持对 SQL 的转换

    方法 Boolean Contains System String 不支持对 SQL 的转换 查询是 IsQueryable 但这停止工作 foreach string s in collection1 if s Length gt 0 q
  • 找时间通过 PHP 执行 MySQL 查询

    我在互联网上看到过这个问题 here http www phpbuilder com board showthread php t 2100256 and here http answers yahoo com question index
  • ZeroDateTimeBehavior=convertToNull 在使用 hibernate 的 jdbc url 中不起作用

    通过 extern 属性文件 url 指定如下 jdbc mariadb xxxxx 3306 xxxxx zeroDateTimeBehavior convertToNull 连接工作正常并且能够查询数据库 通过休眠 我创建了一个映射到带
  • 转置和聚合 Oracle 列数据

    我有以下数据 Base End RMSA Item 1 RMSA Item 2 RMSA Item 3 RMSB Item 1 RMSB Item 2 RMSC Item 4 我想将其转换为以下格式 Key Products RMSA RM
  • 如何使用 PHP 通过 JSON 发送 HTML 元素?

    以下功能 try query this gt pdo gt prepare SELECT FROM bookings WHERE TourID AND dTourDate and Status NOT LIKE Cancelled quer
  • 重复键错误不会取消/回滚mysql事务

    当在 mysql innodb 事务中时 我希望重复的键错误会导致回滚 它没有 相反 它只是抛出一个错误并继续执行下一个命令 一旦到达 COMMIT 命令 事务将被提交 没有重复键导致命令 这是预期的行为吗 如果是这样 如何设置它以便在发生
  • 选择每组最新的项目[重复]

    这个问题在这里已经有答案了 可能的重复 检索每组中的最后一条记录 https stackoverflow com questions 1313120 retrieving the last record in each group 我有 2
  • 从 SQL Server 中的子查询值或其他聚合函数获取平均值

    我有 SQL 语句 SQL Server SELECT COUNT ActionName AS pageCount FROM tbl 22 Benchmark WHERE DATEPART dw CreationDate gt 1 AND
  • 随机排列每行的列值

    我正在使用 C NET 开发多项选择题考试生成器 每次做出报告时 都会在数据库中随机挑选问题 并随机调整选项 我可以做随机问题部分 但我不能做选择的洗牌 我有一张表 其中一行如下 question answer distractor1 di
  • 将sql查询结果写入mysql中的文件

    我正在尝试使用 mysql 将查询结果写入文件 我在一些地方看到了有关 outfile 构造的一些信息 但似乎这只将文件写入正在运行 MySQL 的机器 在本例中是远程机器 即数据库不在我的本地机器上 或者 我还尝试运行查询并从 mysql
  • pyodbc 无法正确处理 unicode 数据

    我确实使用 pyodbc 成功连接了 MySQL 数据库 并且它可以很好地处理 ascii 编码的数据 但是当我打印使用 unicode utf8 编码的数据时 它引发了错误 UnicodeEncodeError ascii codec c
  • DBX 错误:驱动程序无法正确初始化

    我在跑步德尔福XE3 终极版 MySQL 数据库 这是我点击时收到的错误Test Connection 作为回应 我在 xampp 目录中找到了 libmysql 库 并将其复制到我的 System32 目录中 但这是行不通的 此消息指的是
  • mysql 中 INSERT 语句的计算列

    假设我想要一个表来记录其他表中的日期和列数 或者任何类型的数学 字符串连接等 CREATE TABLE log id INTEGER NOT NULL AUTO INCREMENT date DATETIME NOT NULL count

随机推荐

  • 浅谈控制反转(IoC)

    Inversion of Control 什么是控制反转 程序的流程控制权相对于传统的面向过程编程而言发生了反转 下面是维基百科的描述 In software engineering inversion of control IoC is
  • jest测试ajax,搭建Jest前端测试框架总结

    先说一下我要使用Jest的原因 由于开发提测了一个js的公共组件 需要测试人员对此组件的功能进行测试 因为提测的直接就是js文件 所以我们也就只能对其中的方法进行类白盒测试 知道了为什么测 那接下来就是怎么测 很容易的想到了需要一个测试框架
  • 60-200-040-使用-命令-MySQL查看引擎的命令

    文章目录 1 查看存储引擎 2 MySAM 和 InnoDB对比 1 查看存储引擎 mysql gt show ENGINES Engine Support
  • 调制与解调(1)——初认识

    在深入项目前 还需要对调制解调做深入学习 1 基本概念 调制 调制就是使一个信号 如光 高频电磁振荡等 的某些参数 如振幅 频率等 按照另一个欲传输的信号 如声音 图像等 的特点变化的过程 调制是通过改变高频载波的幅度 相位或者频率 使其随
  • 基于VS2019配置opencv4.0

    文章目录 1 前言 2 不说废话 直接上图干净利落 2 1 创建新空白项目 2 2 添加一个主文件 2 3 配置opencv环境 2 4 链接器配置 2 5 将opencv添加到计算机环境中 2 6 文件复制 3 运行测试环境 1 前言 不
  • 安信可SX1278LORA通讯试验

    LoRa 的名字是远距离无线电 Long Range Radio 作为一种线性调频扩频的调制技术 最早由法 国几位年轻人创立的一家创业公司 Cycleo 推出 2012 年 Semtech 收购了这家公司 并将这一调制技术 封装到芯片中 基
  • 3D游戏第八次作业

    3D游戏第八次作业 一 简单粒子制作 按参考资源要求 制作一个粒子系统 参考资源 使用 3 3 节介绍 用代码控制使之在不同场景下效果不一样 1 模拟烟花发射 效果展示 实现 给空对象挂载一个名为moveup的粒子系统模拟烟花发射 Emis
  • java中对象属性可以是另外一个对象或对象的参考

    7 对象的属性可以是另外一个对象或对象的参考 通过这种方法可以迅速构建一个比较大的系统 class Motor Light lights Handle left right KickStart ks Motor lights new Lig
  • 改变MySQL的默认编码

    etc mysql my cnf mysqld character set server utf8 collation server utf8 unicode ci init connect SET collation connection
  • 论文阅读-Exploring Frequency Adversarial Attacks for Face Forgery Detection(探索用于人脸伪造检测的频率对抗性攻击)

    一 论文信息 论文名称 Exploring Frequency Adversarial Attacks for Face Forgery Detection 会议 CVPR 2022 作者团队 二 动机 虽然现有的人脸伪造分类器在检测伪造图
  • Java实现异步的几种方式

    Java实现异步的几种方式 异步编程在对响应时间近乎严苛的今天 受到了越来越多的关注 尤其是在IO密集型业务中 对比传统的同步模式 异步编程可以提高服务器的响应时间和处理业务的能力 从而达到快速给用户响应的效果 代码前置 方法中会直接使用到
  • spring boot引入logback.xml

    logback xml
  • 使用@Value("${xxxx}")注解从配置文件读取值

    使用 Value xxxx 注解从配置文件读取值 记录一下自己学习配置文件读取的方法 假设配置文件为 config properties 1 从配置文件中读取值的用法 Value user username private String u
  • SpringCloud快速入门

    文章目录 1 初识 SpringCloud 1 1 微服务 1 2 简介 2 Eureka 注册中心 2 1 简易模拟一个微服务 2 1 1 搭建EurekaServer 2 1 2 注册到Eureka 2 1 3 从Eureka获取服务
  • golang 将字符串变量中的单引号、双引号和反单引号进行转义

    package main import strconv fmt func main var a string a qwe wer f lopg uiii 随便写的例子 因为字符串变量中的单双引号是我们不能提前知道的 b strconv Qu
  • 企业如何通过CRM系统做好客户管理?

    每一位客户对于企业都是非常宝贵的资源 也是企业赖以生存和发展的基础 做好客户管理和关系维护是企业必备的一种能力 如今 随着信息化的发展 很多企业为了更好的管理客户引进了CRM系统 CRM系统可以帮助企业建立 以客户为中心 的管理方式 将市场
  • 奥特曼系列赛文飞踢是哪个服务器,盘点奥特兄弟最强飞踢技,第一名实至名归你能猜到吗?...

    奥特曼系列较之拳头威力 飞踢这种技能的对比更为奥迷津津乐道 其中最具代表性的无疑是 雷欧飞踢 毕竟有数次杀敌纪录 而提起飞踢的威力对比 雷欧飞踢则不见得一定能傲视群雄 平成系暂且不论 在奥特兄弟中 也不乏能与雷欧飞踢分庭抗礼的飞踢技 力 解
  • 创建数据库(脚本实现)

    创建历史数据库 if object id dbo spr create his db is not null drop procedure dbo spr create his db go create proc dbo spr creat
  • matlab 正弦波 fft,【求助】正弦信号序列fft频谱分析!!!

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 就是正弦包含频率是20hz 20 5hz 40hz 采样频率fs是100hz 分析栅栏效应 先是128个点fft 补零到512个点进行fft 再512个点fft 程序是这样的 N1 128 N2
  • innoDB数据收集方式—永久性&非永久性(四十三)

    上篇文章说了连接查询的成本 主要由驱动表的扇出值和被驱动表的查询方法决定 而成本这些都是可以在 cost 表查看的 因为分为server和engine表 server不管理数据成本 里面包含连接管理 查询缓存 sql解码 sql优化 eng