我在从innodb表中删除数据时遇到一些问题,从我正在阅读的内容中,大多数人都说,释放空间的唯一方法是导出所需数据创建一个新故事并导入它..这似乎非常垃圾的做法,尤其是近3tbs的数据。
我遇到的问题是删除3个月以前的数据以尝试释放磁盘空间,一旦数据被删除,磁盘空间似乎就不会被释放。有没有办法清除或永久删除行/数据以释放磁盘空间?
在没有删除数据库并重新启动服务以释放磁盘空间的情况下,是否有更可靠的方法。
请一些机构可以告诉我处理删除大型数据库的最佳方法。
非常感谢您的高级时间。
谢谢:)
答案 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兔子洞走下去,但这通常会带来更多的麻烦。