1

我在从 innodb 表中删除数据时遇到了一些问题,从我读到的大多数人所说的释放空间的唯一方法是导出想要的数据创建一个新故事并导入它。这似乎是一种非常垃圾的方式这样做,尤其是在将近 3tbs 的数据上。

我遇到的问题是删除超过 3 个月的数据以尝试释放磁盘空间,一旦数据被删除,磁盘空间似乎没有被释放。有没有办法清除或永久删除行/数据以释放磁盘空间?

是否有更可靠的方法,无需删除数据库并重新启动服务以释放磁盘空间。

请有人建议我处理删除大型数据库的最佳方法。

非常感谢您在先进的时间。

谢谢 :)

4

2 回答 2

5

一种相对有效的方法是使用数据库分区并通过删除分区来删除旧数据。它当然需要更复杂的维护,但它确实有效。

首先,启用 innodb_file_per_table 以便每个表(和分区)转到自己的文件而不是单个巨大的 ibdata 文件。

然后,创建一个分区表,每个时间范围(日、月、周,您选择它)有一个分区,这会为您的数据集生成一些合理大小的文件。

create table foo(     
        tid INT(7) UNSIGNED NOT NULL,
        yearmonth INT(6) UNSIGNED NOT NULL,
        data varbinary(255) NOT NULL,
        PRIMARY KEY (tid, yearmonth) 
) engine=InnoDB
PARTITION BY RANGE(yearmonth) (
        PARTITION p201304 VALUES LESS THAN (201304),
        PARTITION p201305 VALUES LESS THAN (201305),
        PARTITION p201306 VALUES LESS THAN (201306)
);

查看数据库数据目录,您会发现每个分区都有一个文件。在此示例中,分区“p201304”将包含 yearmonth < 201304 的所有行,“p201305”将包含 2013-04 的行,“p201306”将包含 2013-05 的所有行。

在实践中,我实际上使用了一个包含 UNIX 时间戳的整数列作为分区键 - 这样随着时间的推移调整分区的大小会更容易。分区边缘不需要匹配任何日历边界,它们可以每 100000 秒发生一次,或者任何导致合理数量的分区(数十个分区)的结果,同时仍然具有足够小的数据文件。

然后,设置一个维护过程,为新数据创建新分区:ALTER TABLE foo ADD PARTITION (PARTITION p201307 VALUES LESS THAN (201307))并删除旧分区:ALTER TABLE foo DROP PARTITION p201304。删除大分区几乎与删除文件一样快,而且实际上会释放磁盘空间。此外,它不会通过在其中分散空白空间来分散其他分区。

如果可能,通过在 WHERE 子句中指定分区键(上例中的年月)或它的范围,确保您的频繁查询只访问一个或几个分区 - 这将使它们运行得更快作为数据库无需查看所有分区内部即可找到您的数据。

于 2013-07-29T15:57:56.767 回答
1

即使您使用该file_per_table选项,您仍然会遇到此问题。“修复”它的唯一方法是重建单个表:

OPTIMIZE TABLE bloated_table

请注意,这将在重建操作期间锁定表,并且您必须有足够的可用空间来容纳新表。在某些系统上,这是不切实际的。

如果您经常删除数据,您可能需要定期轮换整个表。删除 InnoDB 下的表file_per_table几乎会立即释放磁盘空间。如果您每个月有一张表,您可以简单地删除代表三个月前数据的表。

与这些一起工作很难看吗?是的。有替代方案吗?并不真地。您可以尝试沿着表分区兔子洞走下去,但这通常会带来更多的麻烦而不是它的价值。

于 2013-07-29T15:57:31.590 回答