mysql之InnoDB 统计信息收集

ops/2025/2/25 5:08:19/

文章目录

  • InnoDB 统计信息收集
    • 核心概念:统计信息的价值
      • 表级别统计信息
      • 索引级别统计信息
      • 列统计(MySQL 8.0+)
    • 统计信息的存储位置
    • 统计信息的收集方式
      • 自动统计信息收集的触发条件
      • 自动统计信息收集的具体机制
      • 手动统计信息收集: `ANALYZE TABLE` 命令
    • 统计信息的持久化
    • 采样算法原理
      • 动态调整采样 (8.0+改进)
    • 统计信息应用
      • 优化器决策依据
      • 成本计算公式
    • 生产环境调优
      • 采样参数优化建议
      • 监控统计信息健康度
    • 统计信息管理实践
      • 直方图使用案例
    • `innodb_stats_method` 的使用
    • 附:统计信息相关系统变量

InnoDB 统计信息收集

MySQL 查询优化器依赖于准确的统计信息来做出最佳的执行计划决策。对于 InnoDB 存储引擎,统计信息的收集至关重要,它是优化器的 “粮草”。

核心概念:统计信息的价值

统计信息是关于表和索引数据分布的元数据,帮助优化器估算不同执行计划的成本,并选择最优方案。准确的统计信息是 CBO (Cost-Based Optimizer) 做出明智决策的基础。

表级别统计信息

  • 总行数 (Table Rows): 表中记录的总数量。

  • 数据页数量 (Data Pages): 表数据占用的数据页数量。

  • 平均行长度 (Avg Row Length): 每行数据的平均字节数。

  • 表的版本号 (Table Version): 记录表结构或数据修改的次数。

索引级别统计信息

  • Cardinality (基数): 索引列中唯一值的数量。

  • 索引页数量 (Index Pages): 索引结构占用的索引页数量。

  • 索引版本号 (Index Version): 记录索引结构修改的次数。

  • 索引深度(B+树层级)

  • 索引页分布(通过INFORMATION_SCHEMA.INNODB_INDEX_STATS查看)

  • 直方图 (Histogram, 可选): 更详细地描述索引列的数据分布。

列统计(MySQL 8.0+)

  • 直方图(HISTOGRAM):等宽/等高分布统计

统计信息的存储位置

InnoDB 的统计信息主要存储在两个地方:

  1. 数据字典 (Data Dictionary): 系统表,例如 information_schema.TABLES, information_schema.STATISTICS, information_schema.COLUMN_STATISTICS, mysql.innodb_table_stats, mysql.innodb_index_stats
-- 持久化统计信息存储表
SELECT * FROM mysql.innodb_table_stats;  -- 表级统计
SELECT * FROM mysql.innodb_index_stats;  -- 索引级统计
  1. 内存 (Memory): InnoDB 也会在内存中缓存统计信息。

统计信息的收集方式

InnoDB 统计信息收集主要有两种方式:

  1. 自动收集 (Automatic Collection): InnoDB 后台线程自动触发。

  2. 手动收集 (Manual Collection): 通过 ANALYZE TABLE 命令显式触发。

自动统计信息收集的触发条件

  • 表被首次打开 (First Open): 首次访问时,如果统计信息缺失或过期。

  • 表数据发生显著变化 (Significant Data Change): 数据修改达到一定比例 (由 innodb_stats_auto_recalc 控制,默认 ON)。

    • innodb_stats_auto_recalc = ON (默认): 根据数据变化比例自动判断。

    • innodb_stats_auto_recalc = OFF: 禁用自动重新计算。

  • 执行SHOW TABLE STATUS/INDEX

  • 查询INFORMATION_SCHEMA.TABLES/STATISTICS

  • 后台线程异步更新 (Asynchronous Update): 统计信息更新通常是异步的,不阻塞查询。

自动统计信息收集的具体机制

  • 采样 (Sampling): InnoDB 通常采用采样方式,随机读取一定数量的数据页 (由 innodb_stats_sample_pages 控制,默认 8) 进行分析。

    • innodb_stats_sample_pages: 控制采样页数。
  • 版本号 (Version) 机制: 使用版本号跟踪统计信息是否过期。

手动统计信息收集: ANALYZE TABLE 命令

  • 语法: ANALYZE TABLE table_name;

  • 作用: 强制 InnoDB 重新计算统计信息。

  • 执行过程: 默认也会进行采样收集,采样页数由 innodb_stats_sample_pages 控制。

  • 全量扫描选项 (可选): 可以通过 FOR COLUMNS 子句结合 HISTOGRAM 选项,进行全量扫描并生成直方图。

ANALYZE TABLE table_name FOR COLUMNS index_column1, index_column2 HISTOGRAM ON index_column1;
  • 数据归档场景优化, 可以指定分区
-- 分区表统计优化
ALTER TABLE logs ANALYZE PARTITION p2023;  -- 仅更新特定分区统计

统计信息的持久化

InnoDB 统计信息有两种持久化模式,由参数 innodb_stats_persistent 控制:

  • innodb_stats_persistent = ON (默认,MySQL 5.6.6+): 持久化统计信息。

    • 优点: 数据库重启后,统计信息仍然有效。

    • 缺点: 每次更新都需要写入磁盘,略微增加 I/O 开销。

  • innodb_stats_persistent = OFF: 非持久化统计信息。

    • 优点: 更新速度更快,减少 I/O 开销。

    • 缺点: 数据库重启后,统计信息丢失。

innodb_stats_persistent_sample_pages 参数:

  • innodb_stats_sample_pages 类似,但仅在 innodb_stats_persistent = ON 时生效,控制持久化统计信息的采样页数。

  • 如果 innodb_stats_persistent = ON,建议 innodb_stats_persistent_sample_pages 的值大于等于 innodb_stats_sample_pages

采样算法原理

def collect_stats(table):total_pages = get_total_pages(table)sample_pages = min(innodb_stats_persistent_sample_pages, total_pages)sampled_pages = random.sample(range(total_pages), sample_pages)cardinality = 0for page in sampled_pages:index_entries = read_index_entries(page)cardinality += count_distinct(index_entries)# 使用Hasse公式估算基数estimated_cardinality = (cardinality / sample_pages) * total_pages #估算基数 = (采样页总唯一键数 / 采样页数) * 总页数return estimated_cardinality

动态调整采样 (8.0+改进)

自动增加采样页数的情况:

  • 检测到统计信息误差超过15%

  • 索引深度增加超过1层

统计信息应用

优化器决策依据

  • 索引选择: 通过比较全表扫描成本 vs 索引扫描成本

  • 连接顺序优化: 基于各表的筛选后行数估算

  • 范围查询优化: 估算范围扫描需要访问的数据页

分层校准机制:

校准层级触发条件校准方式
页内校准单页唯一键>50%启用位图快速统计
索引校准估算值偏差>30%触发全索引扫描
全局校准表数据变更>25%强制ANALYZE TABLE

成本计算公式

索引扫描成本 = (索引树高度 * 单页IO成本) + (估算行数 * 单行CPU成本) + (估算行数 * 回表IO成本)

生产环境调优

采样参数优化建议

-- 大表优化(亿级数据)
SET GLOBAL innodb_stats_persistent_sample_pages = 200;
-- 高基数列优化
ALTER TABLE users STATS_SAMPLE_PAGES = 100 STATS_PERSISTENT = 1;

监控统计信息健康度

-- 检查统计信息更新时间
SELECT table_name, last_update 
FROM mysql.innodb_table_stats
WHERE database_name = 'mydb';-- 对比估算值与实际值
SELECT table_name,table_rows AS estimated_rows,(SELECT COUNT(*) FROM table_name) AS actual_rows 
FROM information_schema.tables
WHERE table_schema = 'mydb';

统计信息管理实践

直方图使用案例

-- 创建直方图
ANALYZE TABLE users UPDATE HISTOGRAM ON age WITH 50 BUCKETS;-- 查看直方图信息
SELECT * FROM information_schema.column_statistics
WHERE table_name = 'users';

innodb_stats_method 的使用

统计索引列不重复值数量时对 NULL 值的处理, 有三个候选值:

  • nulls_equal:认为所有 NULL 值都是相等的,默认值。

  • nulls_unequal:认为所有 NULL 值都是不相等的。

  • nulls_ignored:直接忽略 NULL 值。

附:统计信息相关系统变量

SHOW VARIABLES LIKE 'innodb_stats%';
-- 关键输出:
-- innodb_stats_method:nulls_equal/null_unequal/nulls_ignored
-- innodb_stats_on_metadata:是否在元数据查询时更新统计

参考:https://relph1119.github.io/mysql-learning-notes/#/mysql ,推荐理解本文之后去看原书,原书有一定深度需前后贯穿仔细理解


http://www.ppmy.cn/ops/161122.html

相关文章

【Python爬虫(46)】解锁分布式爬虫:实时数据处理的奥秘

【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取&#xff…

uniapp修改picker-view样式

解决问题&#xff1a; 1.选中文案样式&#xff0c;比如字体颜色 2.修改分割线颜色 3.多列时&#xff0c;修改两边间距让其平分 展示效果&#xff1a; 代码如下 <template><u-popup :show"showPicker" :safeAreaInsetBottom"false" close&quo…

Linux远程kill进程及$处理

个人博客地址&#xff1a;Linux远程kill进程及$处理 | 一张假钞的真实世界 在远程执行的命令中如果包含特殊字符&#xff08;$&#xff09;时需要转义&#xff0c;如下&#xff1a; ssh rootremote_host "ps -ef|grep process_name | grep -v grep | awk {print $2}&qu…

【后端基础】布隆过滤器原理

文章目录 一、Bloom Filter&#xff08;布隆过滤器&#xff09;概述1. Bloom Filter 的特点2. Bloom Filter 的工作原理 二、示例1. 添加与查询2. 假阳性 三、Bloom Filter 的操作1、假阳性概率2、空间效率3、哈希函数的选择 四、应用 Bloom Filter 是一种非常高效的概率型数据…

使用Hardhat实现ERC20 代币合约详解

ERC20 代币合约详解 &#x1f4b0; 1. 合约概览 // SPDX-License-Identifier: MIT pragma solidity ^0.8.20;import "openzeppelin/contracts/token/ERC20/ERC20.sol";contract MyToken is ERC20 {constructor() ERC20("MyToken", "MTK") {_min…

单臂路由

单臂路由&#xff08;Router on a Stick&#xff09;是一种网络配置方式&#xff0c;主要用于在单个物理接口上实现多个VLAN之间的路由。它通常用于交换机与路由器之间的连接&#xff0c;适用于VLAN间通信需求较小的情况。 工作原理 VLAN划分&#xff1a;交换机上配置多个VLAN…

HarmonyOS学习第5天: Hello World的诞生之旅

鸿蒙初印象&#xff1a;开启探索之门 在操作系统的广袤天地中&#xff0c;HarmonyOS&#xff08;鸿蒙系统&#xff09;宛如一颗冉冉升起的新星&#xff0c;自诞生起便备受瞩目。它由华为倾力打造&#xff0c;是一款基于微内核的全场景分布式操作系统&#xff0c;以其独特的技术…

Python中的Flask深入认知搭建前端页面?

一、Flask 的介绍 1. 什么是Flask&#xff1f; Flask 是一个轻量级的 Python Web 框架&#xff0c;因其简单易用、灵活性高而广受欢迎。它适合快速开发小型应用&#xff0c;也可以通过扩展支持复杂的功能需求。可以结合 HTML、CSS 和 JavaScript 实现丰富的交互功能。 2. 核…