当前位置: 首页 > article >正文

mysql之InnoDB 统计信息收集

文章目录

  • 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 = 0
    for 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.kler.cn/a/558038.html

相关文章:

  • 【Web前端开发精品课 HTML CSS JavaScript基础教程】第二十五章课后题答案
  • MySQL数据库——表的约束
  • 基于数据可视化+SpringBoot+安卓端的数字化施工项目计划与管理平台设计和实现
  • Infuse Pro for Mac v8.1 全能视频播放器 支持M、Intel芯片
  • Lua 面向对象
  • Vue3 前端路由配置 + .NET8 后端静态文件服务优化策略
  • 力扣——杨辉三角
  • 基于数据可视化+SpringBoot+安卓端的数字化OA公司管理平台设计和实现
  • 具有整合各亚专科医学领域知识能力的AI智能体开发纲要(2025版)
  • 模拟实现Java中的计时器
  • 边缘计算网关:圆织机设备数据洞察的 “智慧之眼”
  • 《A++ 敏捷开发》- 20 从 AI 到最佳设计
  • TCP传输可靠性保障:理论讲解→实战面试解析
  • Linux lsblk 命令详解:查看磁盘和分区信息 (中英双语)
  • 区块链相关方法-波士顿矩阵 (BCG Matrix)
  • 《论模型驱动架构设计方法及其应用》审题技巧 - 系统架构设计师
  • Ubuntu 查看mysql用户和数据库
  • Qwen2.5-VL Technical Report!!! 操作手机电脑、解析化学公式和乐谱、剪辑电影等,妥妥六边形战士 !...
  • Jmeter HTTP代理服务器录制压力脚本
  • MySQL 架构