如何回收MySql磁盘空间

我在
MySql服务器中有一个表,该表包含大约1M行.仅因为一个列表每天占用更多磁盘空间.此列的数据类型为Mediumblob.表大小约为90 GB.

在每行插入之后,我做了一些处理然后我真的不需要这个列.

因此对于此列,如果我在处理行后将值设置为NULL,MySql是否利用此空白空间进行下一行插入?

MySql Server详细信息

服务器版本:5.7

引擎:InnoDB

托管:Google Cloud Sql

编辑1:
我从表中删除了90%的行,然后运行了OPTIMIZE TABLE table_name
但它只减少了4GB的磁盘空间,并且没有回收可用磁盘空间.

编辑2
我甚至删除了我的数据库并创建了新的数据库和表,但MySql服务器仍然显示80GB的磁盘空间. MySQL服务器的所有数据库的大小

SELECT table_schema "database name",
         sum( data_length + index_length ) / 1024 / 1024 "database size in MB",
         sum( data_free )/ 1024 / 1024 "free space in MB"
     FROM information_schema.TABLES
     GROUP BY table_schema; 

+--------------------+---------------------+------------------+
| database name      | database size in MB | free space in MB |
+--------------------+---------------------+------------------+
| information_schema |          0.15625000 |      80.00000000 |
| app_service        |         15.54687500 |       4.00000000 |
| mysql              |          6.76713467 |       2.00000000 |
| performance_schema |          0.00000000 |       0.00000000 |
| sys                |          0.01562500 |       0.00000000 |
+--------------------+---------------------+------------------+

谢谢

最佳答案 编辑:从下面的评论中可以看出,用户的二进制日志是罪魁祸首.有意义的是,在很多DELETE之后二进制日志会很大,并且假设MySQL实例使用基于行的复制.

答案很复杂.

您可以使用NULL而不是实际值来节省空间.对于详细信息,InnoDB每行仅使用1位来指示该值为NULL(请参阅我对https://stackoverflow.com/a/230923/20860的旧答案).

但这只会在存储该行的页面中留出空间.每个页面只能存储同一个表中的行.因此,如果将其中的一组设置为NULL,则会在该页面中创建空间,该空间仅可用于该表的后续插入.它不会使用属于其他表的行的间隙.

并且它仍然可能不会被重用于mediumblob表的任何行,因为InnoDB以主键顺序存储行.给定表的页面不必是连续的,但我猜测页面中的行可能是连续的.换句话说,您可能无法在页面中的主键随机顺序中插入行.

我肯定不知道这个细节,你必须阅读Jeremey Cole’s research on InnoDB storage才能知道答案.这是一段摘录:

The actual on-disk format of user records will be described in a future post, as it is fairly complex and will require a lengthy explanation itself.

User records are added to the page body in the order they are inserted (and may take existing free space from previously deleted records), and are singly-linked in ascending order by key using the “next record” pointers in each record header.

是否可以按顺序插入行并重用页面上的空间仍然不太清楚.

因此,您可能只会严重破坏页面,并且无论如何都会将具有高主键值的新行添加到其他页面.

如果您不时使用OPTIMIZE TABLE,您可以更好地回收空间,这将有效地将整个表重写为新页面.这可能会重新打包行,如果您将值更改为NULL,则会在每个页面中插入更多行.

删除不需要的行会更有效,然后是OPTIMIZE TABLE.这将消除整个页面,而不是让它们碎片化.

点赞