2013-07-29 127 views
1

我在删除innodb表中的数据时出现了一些问题,从我正在阅读的大多数人都说,释放空间的唯一方法是导出所需的数据创建一个新的故事并导入它..这似乎是一个非常垃圾的做法,特别是在接近3吨的数据。MySQL Inndob从非常大的数据库中删除/清除行

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

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

请一些机构建议我处理删除大型数据库的最佳方法。

非常感谢您的高级时间。

谢谢:)

+0

可能重复的[MySQL数据文件不会缩小](http://stackoverflow.com/questions/2646373/mysql-data-file-wont-shrink) –

回答

1

即使你使用file_per_table选项,你仍然有这个问题。 “修正”的唯一方法是重建单个表:

OPTIMIZE TABLE bloated_table 

注意,这将重建操作过程中锁定表,你必须有足够的自由空间来容纳新表。在某些系统上这是不切实际的。

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

与这些工作是丑陋的吗?是。有其他选择吗?不是真的。你可以尝试去掉table partitioning兔子洞,但是这往往会导致更多的麻烦。

+0

如果磁盘非常满,会发生什么情况优化失败?我猜这可能是定期维护的好方案。由于数据库磁盘空间为100%(19 GB免费),我想我可能错过了这条船,我可能不得不将数据库痛苦地移动到更大的磁盘驱动器,并开始定期删除/优化维护计划。这听起来像是解决它的最好方法吗?谢谢:) – deejuk

+1

OPTIMIZE TABLE将创建该表的新副本,然后删除旧表。如果你的表很大,并且你没有设置file_per_table,那么这个操作可以使你的ibdata文件增加新数据集的大小 - 并且在这之后它不会缩小。即使使用file_per_table,在最坏情况下设置单个大型表的情况下,由于在OPTIMIZE期间需要空间来存储表副本,常规OPTIMIZE时间表可能会增加磁盘空间要求。如果你有很多大桌子,这不是一个问题,但仍然会锁定你的桌子很长一段时间。 – oh7lzb

+1

“每月表格”是一个可行的选项,但是在所有INSERT/DELETE/UPDATE操作中,您需要额外的特殊代码才能选择正确的表格。使用分区将魔术带到分区创建/删除维护代码。 – oh7lzb

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子句中指定分区键(上例中的yearmonth)或其范围,确保您的频繁查询只访问一个或几个分区 - 这将使它们运行很多因为数据库不需要查看所有分区以查找数据,所以速度更快。

+0

我会玩你的建议,非常感谢你的帮助。 – deejuk

+0

这将如何工作,如果我想一次从多个表中删除使用表中的ID或我需要使用连接? – deejuk

+0

对于分区模式,您可以执行“ALTER TABLE foo DROP PARTITION p201304”操作,该操作实际上会从磁盘中删除单个分区文件,并立即清除一个月的数据(或任何您的分区时间步骤恰巧)。你不能做一个JOIN。您仍然可以像以前一样使用DELETE删除较少量的数据(包括JOIN和所有这些数据),但这不会让您获得分区删除的速度,并且在分区被删除之前它不会回收磁盘空间。 http://dev.mysql.com/doc/refman/5.5/en/alter-table-partition-operations.html – oh7lzb