我在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 |
+--------------------+---------------------+------------------+
由于
答案 0 :(得分:1)
编辑:从下面的评论中可以看出,用户的二进制日志是罪魁祸首。在很多DELETE之后,二进制日志会很大,假设MySQL实例使用基于行的复制,这是有意义的。
答案很复杂。
您可以使用NULL而不是实际值来节省空间。 InnoDB每行每列仅使用1位来表示该值为NULL(有关详细信息,请参阅我对https://stackoverflow.com/a/230923/20860的旧答案)。
但这只会在存储该行的页面中留出空间。每个页面只能存储同一个表中的行。因此,如果您将其中的一组设置为NULL,则会在该页面中创建空间,该空间可用于后续插入仅适用于该表。它不会对属于其他表的行使用间隙。
它仍然可能无法重复用于您的mediumblob表的任何行,因为InnoDB以主键顺序存储行。给定表的页面不必是连续的,但我猜测页面中的行可能是连续的。换句话说,您可能无法在页面中的主键随机顺序中插入行。
我确实不知道这个细节,你必须阅读Jeremey Cole's research on InnoDB storage才能知道答案。这是一段摘录:
用户记录的实际磁盘格式将在以后的文章中描述,因为它相当复杂,本身需要冗长的解释。
用户记录按插入顺序添加到页面正文中(并且可以从先前删除的记录中获取现有可用空间),并使用每个记录中的“下一条记录”指针按键按升序单链接报头中。
仍然不太清楚行是否可以按顺序插入,并重用页面上的空间。
因此,您可能只会严重破坏页面,并且无论如何都会将具有高主键值的新行添加到其他页面。
如果您不时使用OPTIMIZE TABLE
,您可以更好地回收空间,这将有效地将整个表重写为新页面。这个可能重新打包行,如果您将值更改为NULL,则会在每个页面中插入更多行。
删除不需要的行会更有效,然后是OPTIMIZE TABLE。这将消除整个页面,而不是让它们分散。