织梦数据库碎片优化命令

数据库碎片是长期增删改后留下的"数据空洞",会让查询变慢、占用磁盘。定期优化可恢复性能。

一、碎片产生原理

MySQL InnoDB 引擎删除数据后不会立即释放磁盘空间,而是标记为可复用。长期累积形成"碎片",导致数据文件比实际数据大 30%-50%,查询需要扫描更多页,IO 增加。

二、检测碎片命令

2.1 查看所有表碎片率

SELECT
  table_name,
  ROUND(data_length/1024/1024,2) AS data_mb,
  ROUND(index_length/1024/1024,2) AS index_mb,
  ROUND(data_free/1024/1024,2) AS free_mb,
  ROUND(data_free/(data_length+index_length+1)*100,2) AS frag_pct
FROM information_schema.tables
WHERE table_schema='dede_db'
ORDER BY free_mb DESC;

frag_pct 超过 20% 即需优化。

三、优化命令

3.1 OPTIMIZE TABLE(推荐)

OPTIMIZE TABLE dede_archives;
OPTIMIZE TABLE dede_addonarticle;
OPTIMIZE TABLE dede_arctiny;
OPTIMIZE TABLE dede_taglist;

3.2 ALTER TABLE 重建

ALTER TABLE dede_archives ENGINE=InnoDB;

等价于 OPTIMIZE,但需注意会锁表。

3.3 ANALYZE 更新统计

ANALYZE TABLE dede_archives;

更新索引统计信息,让查询优化器选择更优执行计划。

四、批量优化脚本

#!/bin/bash
# optimize_all_tables.sh
DB_USER="root"
DB_PASS="yourpass"
DB_NAME="dede_db"

TABLES=$(mysql -u$DB_USER -p$DB_PASS -e "SHOW TABLES" $DB_NAME | tail -n +2)
for t in $TABLES; do
    echo "优化 $t ..."
    mysql -u$DB_USER -p$DB_PASS -e "OPTIMIZE TABLE $t;" $DB_NAME
done
echo "全部完成"

五、织梦主要表的优化顺序

表名用途优化优先级
dede_archives文档主表
dede_addonarticle正文
dede_arctiny索引
dede_taglisttag关联
dede_log日志
dede_search_cache搜索缓存

六、常见问题原因分析

6.1 优化期间站点卡顿

原因:OPTIMIZE 会锁表,期间无法读写。

解决:凌晨低峰期执行;或使用 pt-online-schema-change 在线操作。

6.2 优化后磁盘未释放

原因:InnoDB 共享表空间 ibdata1 不会回收空间。

注意:若使用共享表空间,需导出数据 → 删除 ibdata1 → 重新导入才能真正释放空间。

七、配置 innodb_file_per_table

建议开启独立表空间,让每张表使用独立 .ibd 文件,OPTIMIZE 即可释放磁盘:

# my.cnf
[mysqld]
innodb_file_per_table=1

八、定时优化任务

宝塔 → 计划任务 → 每周日凌晨 3 点执行:

0 3 * * 0 /bin/bash /root/optimize_all_tables.sh >> /www/wwwlogs/db_optimize.log

九、行动指引

建议建立数据库健康度监控:每周记录碎片率、表大小、慢查询数。结合宝塔可视化监控面板观察磁盘 IO 趋势,发现异常及时优化。同时关注 MySQL 慢查询日志,将优化重心从"碎片清理"逐步延伸到"索引调优",让数据库性能持续稳定。