mysql 的analyze与 optimize命令
一、analyze table - 更新统计信息
1. 基本语法与功能
analyze [no_write_to_binlog | local] table tbl_name [, tbl_name] ...
作用:收集表统计信息用于优化器生成更优的执行计划,主要更新:
- 索引基数(cardinality)
- 数据分布直方图(mysql 8.0+)
- 表的存储引擎统计信息
2. 使用场景
-- 单表分析 analyze table customers; -- 多表分析(适用于批量维护) analyze table orders, order_items; -- 不写入二进制日志(主从复制环境) analyze no_write_to_binlog table large_table;
3. 执行效果验证
-- 查看索引统计信息 show index from customers; -- 查看直方图信息(mysql 8.0+) select * from information_schema.column_statistics where table_name = 'customers';
4. 自动分析配置
-- 查看自动分析设置 show variables like 'innodb_stats_auto_recalc'; -- 设置自动分析阈值(默认10%变化触发) set global innodb_stats_persistent_sample_pages = 200; alter table customers stats_sample_pages = 500;
二、optimize table - 表优化重组
1. 基本语法与功能
optimize [no_write_to_binlog | local] table tbl_name [, tbl_name] ...
作用(根据存储引擎不同):
- innodb:重建表,整理碎片(实际是alter table的包装)
- myisam:修复碎片、排序索引、更新统计
- archive:重新压缩表数据
2. 使用场景
-- 单表优化 optimize table order_archive; -- 批量优化所有表 select concat('optimize table ', table_name, ';') from information_schema.tables where table_schema = 'mydb' and engine = 'innodb' into outfile '/tmp/optimize_tables.sql'; source /tmp/optimize_tables.sql;
3. 执行效果验证
-- 查看表碎片率(innodb) select table_name, data_free / (data_length + index_length) as frag_ratio from information_schema.tables where table_schema = 'mydb' and data_length > 0; -- 优化前后性能对比 explain analyze select * from large_table where create_time > '2023-01-01';
4. 替代方案(避免锁表)
-- 使用pt-online-schema-change工具(percona toolkit) pt-online-schema-change --alter="engine=innodb" d=mydb,t=large_table -- 使用gh-ost工具(github) gh-ost --alter="engine=innodb" --database=mydb --table=large_table
三、核心区别对比
特性 | analyze table | optimize table |
---|---|---|
主要目的 | 更新统计信息 | 物理重组表结构 |
锁级别 | 通常仅读锁 | 表锁(innodb为mdl锁) |
执行时间 | 通常较快 | 大表可能很慢 |
存储引擎影响 | 所有引擎都需要 | 不同引擎效果不同 |
空间回收 | 不会回收空间 | 可能回收空间 |
自动触发机制 | 有(innodb_stats_auto_recalc) | 无 |
四、最佳实践指南
1. 维护计划建议
-- 每周维护脚本示例 set @db = 'mydb'; set @threshold = 0.3; -- 碎片率阈值 select concat('analyze table ', table_name, ';') as analyze_cmd from information_schema.tables where table_schema = @db and engine = 'innodb'; select concat('optimize table ', table_name, ';') as optimize_cmd from ( select table_name, data_free / (data_length + index_length) as frag_ratio from information_schema.tables where table_schema = @db and engine = 'innodb' and data_length > 0 ) t where frag_ratio > @threshold;
2. 生产环境注意事项
- 避开高峰期:在低负载时段执行optimize
- 备份优先:执行前确保有有效备份
- 监控进度:
watch -n 1 "mysql -e 'show processlist' | grep -i optimize"
- 考虑替代方案:
-- innodb碎片整理替代方案 alter table large_table engine=innodb; -- 使用percona的pt-index-usage分析索引 pt-index-usage /var/lib/mysql/mysql-slow.log
3. 性能监控指标
-- 查询效率变化监控 select * from sys.schema_table_statistics where table_schema = 'mydb'; -- 碎片率监控视图 create view frag_monitor as select table_schema, table_name, round(data_free/(1024*1024),2) as frag_mb, round(data_free/(data_length+index_length)*100,2) as frag_pct from information_schema.tables where data_length > 0 order by frag_mb desc;
五、常见问题解决方案
1. 长时间阻塞问题
-- 查看阻塞会话 select * from performance_schema.threads where processlist_command = 'query' and processlist_state like '%optimize%'; -- 安全终止优化操作 kill [process_id];
2. 空间不足问题
# 检查磁盘空间 df -h /var/lib/mysql # 临时更改tmpdir(需要重启) [mysqld] tmpdir = /mnt/bigtmp
3. 复制环境处理
-- 从库延迟监控 show slave status\g -- 使用no_write_to_binlog optimize no_write_to_binlog table audit_log;
4. 大表优化策略
# 分块优化(使用pt-archiver) pt-archiver --source h=localhost,d=mydb,t=large_table \ --purge --where "1=1" --limit 1000 --commit-each
通过合理使用analyze table和optimize table,可以保持mysql数据库性能稳定。对于关键业务表,建议建立定期的统计信息收集和碎片整理计划,同时结合现代监控工具持续跟踪表健康状况。
到此这篇关于mysql 的analyze与 optimize命令的文章就介绍到这了,更多相关mysql analyze和optimize命令内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论