MySQL统计信息

1. 什么是统计信息?

统计信息就像是数据库的"地图",它告诉优化器:

  • 每个表有多大(有多少行数据)

  • 每个索引的"区分度"(有多少不同的值)

  • 数据分布情况(哪些值出现频率高)

2. 为什么需要统计信息?

想象你要找一本图书馆的书:

  • 没有统计信息:盲目地在每个书架搜索

  • 有统计信息:直接去最可能存放的书架查找

二、统计信息核心内容全景图

统计信息类型 存储位置 更新方式 影响范围
表大小/行数 data_dictionary 自动/手动ANALYZE 全表扫描成本计算
索引基数(Cardinality) mysql.innodb_index_stats 自动/手动ANALYZE 索引选择
直方图(Histogram) column_statistics 手动ANALYZE TABLE 等值查询优化
索引深度 内存计算 自动 范围查询效率

三、统计信息全生命周期管理

1. 创建阶段

sql 复制代码
-- 创建表时指定统计信息策略
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    INDEX (name)
) STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;

2. 更新机制

自动更新触发条件

  • 表中数据变化超过10%(默认阈值)

  • 第一次打开表时

  • 执行SHOW TABLE STATUS时(某些版本)

手动更新方法

sql 复制代码
-- 标准语法
ANALYZE TABLE users;

-- 更新直方图统计(MySQL 8.0+)
ANALYZE TABLE users UPDATE HISTOGRAM ON name WITH 32 BUCKETS;
  1. 监控方法
sql 复制代码
-- 检查统计信息时效性
SELECT 
    table_name,
    update_time,
    CONCAT(ROUND(data_length/1024/1024,2),'MB') AS size,
    IF(DATEDIFF(NOW(),update_time)>7,'⚠️过期','✅正常') AS status
FROM 
    information_schema.tables
WHERE 
    table_schema=DATABASE();

-- 查看索引统计详情
SELECT * FROM mysql.innodb_index_stats WHERE table_name='users';

四、生产环境最佳实践

1. 参数配置建议

sql 复制代码
[mysqld]
# 启用持久化统计(重启不丢失)
innodb_stats_persistent=ON
# 自动重新计算统计
innodb_stats_auto_recalc=ON
# 增加采样页面提高准确性
innodb_stats_persistent_sample_pages=32

2. 维护方案

日常维护

sql 复制代码
-- 每周维护脚本示例
SET @db = DATABASE();
SELECT CONCAT('ANALYZE TABLE ', table_name, ';') 
FROM information_schema.tables 
WHERE table_schema = @db 
  AND DATEDIFF(NOW(),update_time) > 7
INTO OUTFILE '/tmp/analyze_tables.sql';
SOURCE /tmp/analyze_tables.sql;

大表特殊处理

sql 复制代码
# 使用pt-table-sync分批分析
pt-table-sync --analyze h=localhost,D=dbname,t=large_table

五、常见问题解决方案

1. 统计信息不准的症状

  • 执行计划突然变差

  • 相同的查询有时快有时慢

  • EXPLAIN显示预估行数与实际严重不符

2. 紧急处理方法

sql 复制代码
-- 立即刷新问题表的统计信息
FLUSH TABLE users;
ANALYZE TABLE users;

-- 强制使用指定索引(临时方案)
SELECT /*+ INDEX(users name_idx) */ * FROM users WHERE name LIKE 'A%';

3. 自动化监控方案

sql 复制代码
-- 创建监控事件
CREATE EVENT monitor_stats
ON SCHEDULE EVERY 1 DAY
DO
BEGIN
    DECLARE cnt INT;
    SELECT COUNT(*) INTO cnt FROM information_schema.tables 
    WHERE table_schema=DATABASE() AND DATEDIFF(NOW(),update_time)>7;
    
    IF cnt > 0 THEN
        -- 发送报警邮件或记录日志
        CALL send_alert(CONCAT(cnt, ' tables need analyze'));
    END IF;
END;

六、可视化学习工具

  1. 统计信息查看

    sql 复制代码
    -- 使用MySQL Workbench可视化统计信息
    -- 右键表 → Table Inspector → Indexes/Statistics
  2. 执行计划对比

    sql 复制代码
    -- 更新统计前后对比
    EXPLAIN FORMAT=TREE SELECT * FROM users WHERE age > 30;
    ANALYZE TABLE users;
    EXPLAIN FORMAT=TREE SELECT * FROM users WHERE age > 30;
相关推荐
云飞云共享云桌面3 分钟前
钣金制造研发优化:不采购传统工作站,实现 SolidWorks 团队共用服务器开展三维建模
运维·服务器·网络·数据库·3d·制造
4SAPI14 分钟前
2026年大模型API接入选型指南:企业与个人用户的架构、稳定性与成本考量
大数据·开发语言·数据库·人工智能·架构·php
她说..26 分钟前
MySQL 与 Java 的 JSON 数据处理
java·mysql·json·springboot
xixiaoyunya28 分钟前
只备份数据远远不够:服务器系统备份的完整方案与实践
服务器·网络·数据库
大模型丫丫1 小时前
LangGraph + MCP(Model Context Protocol)完整讲解
java·开发语言·数据库
我不是程序员三三1 小时前
怎么监控电脑?企业办公终端监控建设实战与合规要点
服务器·数据库·电脑
这个DBA有点耶1 小时前
时间序列数据库选型2026:5款主流产品深度对比与场景适配
大数据·数据库·程序人生·架构·时序数据库·dba·数据库管理员
砚底藏山河1 小时前
拉数管道设计:从一次性脚本到可重启的数据流水线(魔码量化实战 #01)
java·数据库·python·金融·maven
2601_966377131 小时前
运营商密评密改落地实践:透明加密解决密码应用合规与安全痛点
数据库·安全·oracle
伯恩bourne1 小时前
Qdrant 快速入门 :数据模型介绍
服务器·数据库·人工智能