一個相對有效的方法是使用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)或其範圍,確保您的頻繁查詢只訪問一個或幾個分區 - 這將使它們運行很多因爲數據庫不需要查看所有分區以查找數據,所以速度更快。
可能重複的[MySQL數據文件不會縮小](http://stackoverflow.com/questions/2646373/mysql-data-file-wont-shrink) –