MySQL Innodb从非常大的数据库中删除/清除行

时间:2013-07-29 15:30:52

标签: php mysql database innodb lamp

我在从innodb表中删除数据时遇到一些问题,从我正在阅读的内容中,大多数人都说,释放空间的唯一方法是导出所需数据创建一个新故事并导入它..这似乎非常垃圾的做法,尤其是近3tbs的数据。

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

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

请一些机构可以告诉我处理删除大型数据库的最佳方法。

非常感谢您的高级时间。

谢谢:)

2 个答案:

答案 0 :(得分:5)

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

首先,启用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子句中指定分区键(上例中的年份)或其中的一个范围 - 这将使它们运行得更快因为数据库不需要查看所有分区以查找数据。

答案 1 :(得分:1)

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

OPTIMIZE TABLE bloated_table

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

如果您经常删除数据,则可能需要定期轮换整个表格。使用file_per_table删除InnoDB下的表将几乎立即释放磁盘空间。如果您每月有一个表,则只需删除表示三个月前数据的表。

使用这些是否丑陋?是。还有其他选择吗?并不是的。您可以尝试沿着table partitioning兔子洞走下去,但这通常会带来更多的麻烦。