MySQL磁盘碎片清理

1,003 阅读2分钟

MySQL磁盘碎片清理

磁盘碎片产生的原因

为什么会产生磁盘碎片?那是因为某一个表如果经常插入数据和删除数据,必然会产生很多未使用的空白空间,这些空白空间就是不连续的碎片,这样久而久之,这个表就会占用很大空间,但实际上表里面的记录数却很少,这样不但会浪费空间,并且查询速度也更慢。

查看除系统表外磁盘碎片占用空间[date_free]大于0的所有表信息

-- 查看除系统表外 data_free 值大于0 的所有表的信息

SELECT
    concat(TABLE_SCHEMA,'.',TABLE_NAME)                                         AS database_name,
    concat(TRUNCATE(SUM(DATA_LENGTH+DATA_FREE+INDEX_LENGTH)/1024/1024,2),' MB') AS total_size,
    concat(TRUNCATE(SUM(DATA_LENGTH)/1024/1024,2),' MB')                        AS data_size,
    concat(TRUNCATE(SUM(DATA_FREE)/1024/1024,2),' MB')                          AS data_free,
    concat(TRUNCATE(SUM(INDEX_LENGTH)/1024/1024,2),'MB')                        AS index_size,
    ENGINE
FROM information_schema.tables
WHERE table_schema NOT IN ('information_schema',
                           'mysql')
    AND data_free > 0
GROUP BY
    TABLE_NAME,
    TABLE_SCHEMA,
    ENGINE
ORDER BY
    data_free DESC;

清理磁盘碎片的两种方式

  • OPTIMIZE TABLE 表名;
-- OPTIMIZE TABLE只对MyISAM、BDB和InnoDB表起作用
OPTIMIZE TABLE tb_task_log;

执行结果会出现 “Table does not support optimize, doing recreate + analyze instead”,这个其实无妨,实际上磁盘碎片已经被清除掉了。

  • ALTER TABLE 表名 ENGINE = Innodb;(注意:只有InnoDB引擎的表可以这么做)
ALTER TABLE tb_operational_log engine=InnoDB;

注意:OPTIMIZE操作会暂时锁住表,而且数据量越大,耗费的时间也越长,它毕竟不是简单查询操作。所以把OPTIMIZE命令放在程序中是不妥当的,不管设置的命中率多低,当访问量增大的时候,整体命中率也会上升,这样肯定会对程序的运行效率造成很大影响。比较好的方式就是做个shell,定期检查mysql中 information_schema.TABLES字段,查看DATA_FREE字段,大于0的话,就表示有碎片,然后启动脚本。