一、背景
一天,观察到线程DB占用了超过1T的空间,但是show table status from mc查看,所有表加起来也只不过是300G左右,远没有1T,于是想探个究竟。
二、分析
分析一:让DBA帮看下,binlog占用了81G,innodata占用16G,innolog占用6G,主要还是data占用了930G,还是要看下为什么data这么大
分析二:各个表占用的总大小
、
分析三: select table_name,Data_length,Index_length,data_free from information_schema.tables where table_schema='mc' order by data_free desc;
通过以上命令可以看数据大小,各个字段含义:
Data_length:表存储的数据大小
Index_length:索引大小
data_free :碎片大小(其实就是delete数据导致索引空间没释放,从而产生碎片
执行sql可知,noticelog和handle两个表的碎片分别达到了203G和44G,碎片会影响查询效率,所以需要定期清理
三、表碎片产生原因
经常进行 delete 操作,产生空白空间,如果进行新的插入操作,MySQL将尝试利用这些留空的区域,但仍然无法将其彻底占用,久而久之就产生了碎片;
简单理解就是,原来一条记录是10KB,被删除后,变成空白空间,这个空间不会回收,新数据会插入到这个空白空间,但是如果新数据是2KB,相当于8KB的空间被浪费了,这8KB的空间就是碎片。
当删除的数据多了就会产生碎片。
四、碎片的影响
1、占用空间:如上mc_noticelog表的碎片占用了超过了200G的空间。
2、对性能的影响:性能影响不大,但是对于查询操作,需要扫描的是所有空间,会有一点影响,下面是网络上摘录的一句话
一个表有1万行,每行10字节,会占用10万字节存储空间,执行删除操作,只留一行,实际内容只剩下10字节,但MySQL在读取时,仍看做是10万字节的表进行处理,所以,碎片越多,就会越来越影响查询性能。