四时宝库

程序员的知识宝库

如何利用optimize、存储过程和系统表对mysql数据库批量碎片清理

概述

简单写了一个存储过程对mysql数据库中的表进行批量碎片清理,建议在业务空闲时间段进行。


思路

核心是利用mysql系统表和“optimize table 表名”命令,对mysql数据表进行空间的释放。由于delete和drop table都不会释放表空间(truncate 命令会释放表空间),所以需要利用optimize 命令进行释放。

这个存储过程目的是给一个库的所有表来整理碎片的。一个表随着插入很频繁,或者一直更新不停的,就会积累好多碎片。如果及时整理一下,查询效率会高出好多。


存储过程

整理如下:

DELIMITER $
DROP PROCEDURE IF EXISTS `mysql`.`sp_optimize_tables`$
CREATE PROCEDURE `mysql`.`sp_optimize_tables`(
 IN db_name varchar(255))
BEGIN
 -- To optimize all the tables in exact database.
 declare cnt int default 0;
 declare i int default 0;
 select count(*) as total from information_schema.tables where table_schema = db_name into cnt;
 while i < cnt
 do
 -- Get the table's exact name.
 set @stmt = concat('select table_name from information_schema.tables where table_schema = ''',db_name,''' order by table_name asc limit ',i,',1 into @tb_name');
 prepare s1 from @stmt;
 execute s1;
 drop prepare s1;
 set @stmt = '';
 set @stmt = concat('optimize table ',db_name,'.',@tb_name);
 prepare s1 from @stmt;
 execute s1;
 drop prepare s1;
 set @stmt = '';
 set i = i + 1;
 end while;
 -- Refresh tables.
 flush tables;
END$
DELIMITER ;

因为optimize有一些限定条件,所以也可以改成alter ... engine=innodb;这种方式。

DELIMITER $
DROP PROCEDURE IF EXISTS `mysql`.`sp_optimize_tables2`$
CREATE PROCEDURE `mysql`.`sp_optimize_tables2`(
 IN db_name varchar(255))
BEGIN
 -- To optimize all the tables in exact database.
 declare cnt int default 0;
 declare i int default 0;
 select count(*) as total from information_schema.tables where table_schema = db_name into cnt;
 while i < cnt
 do
 -- Get the table's exact name.
 set @stmt = concat('select table_name from information_schema.tables where table_schema = ''',db_name,''' order by table_name asc limit ',i,',1 into @tb_name');
 prepare s1 from @stmt;
 execute s1;
 drop prepare s1;
 set @stmt = '';
 set @stmt = concat('alter table ',db_name,'.',@tb_name,' engine=innodb');
 prepare s1 from @stmt;
 execute s1;
 drop prepare s1;
 set @stmt = '';
 set i = i + 1;
 end while;
 -- Refresh tables.
 flush tables;
END$
DELIMITER ;

调用示例:

mysql> use mysql
mysql> call sp_optimize_tables('database_name');

因为我这表都是innodb,所以采用alter table XX engine=innodb方式。

mysql> use mysql
mysql> call sp_optimize_tables2('database_name');

觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接