2013-07-29 162 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