2012-12-03 44 views
3

我有一個由MYISAM表組成的數據庫模式,我有時會從一些表中刪除舊的記錄。LOAD DATA在刪除後回收磁盤空間

我知道刪除並不回收內存空間,但正如我在DELETE命令的描述中發現,插入件可重複使用的空間刪除

在MyISAM表,刪除的行被保持在一個鏈表和後續的INSERT操作將重用舊的行位置。

我很感興趣,如果LOAD DATA命令也重用已刪除的空間?

UPDATE

我也有興趣索引空間如何回收?

UPDATE 2012年12月3日23:11

一些更多的信息供貨基於答案從@RolandoMySQLDBA

收到執行以下建議的查詢我得到了不同的表不同的結果後,其空間需要被重新使用或回收:

SELECT row_format FROM information_schema.tables 
WHERE table_schema='mydb' AND table_name='mytable1'; 

>Dynamic

SELECT row_format FROM information_schema.tables 
WHERE table_schema='mydb' AND table_name='mytable2'; 

>Fixed

UPDATE 2012年12月9日08:06

LOAD DATA不要重新使用以前刪除的空間當且僅當行格式(我已經通過運行一個簡短的腳本檢查了它)是固定的還是(行格式是動態的,並且存在具有完全相同大小的刪除行)。

似乎如果row_format是動態的,則會爲每個記錄對已刪除列表進行完整查找,並且如果未找到確切的行大小,則不會使用已刪除的記錄,並且表內存使用率將會提高,另外LOAD DATA將需要更多時間導入記錄。

我會除了在這裏給出的答案,因爲它完美地描述了所有的過程。

回答

4

對於MySQL表稱爲mydb.mytable只是運行以下命令:

OPTIMIZE TABLE mydb.mytable; 

你也可以做到這一點的階段:

CREATE TABLE mydb.mytable_new LIKE mydb.mytable; 
ALTER TABLE mydb.mytable_new DISABLE KEYS; 
INSERT INTO mydb.mytable_new SELECT * FROM mydb.mytable; 
ALTER TABLE mydb.mytable_new ENABLE KEYS; 
ALTER TABLE mydb.mytable RENAME mydb.mytable_old; 
ALTER TABLE mydb.mytable_new RENAME mydb.mytable; 
ALTER TABLE mydb.mytable_old; 
ANALYZE TABLE mydb.mytable; 

在這兩種情況下,該表沒有碎片結束。

試試吧!

UPDATE 2012年12月3日12:50 EDT

如果你關注與否行通過LOAD DATA INFILE在批量插入重複使用,請注意以下幾點:

當你創建了MyISAM表中,我假定默認的行格式是動態的。您可以檢查它與任何

SHOW CREATE TABLE mydb.mytable\G 

SELECT row_format FROM information_schema.tables 
WHERE table_schema='mydb' AND table_name='mytable'; 

因爲你的表的行格式是Dynamic,零散行是各種大小的東西。 MyISAM存儲引擎會持續檢查每個被刪除的行的長度,以確定下一組要插入的數據是否適合。如果傳入的數據不適合任何已刪除的行,則會附加新的行數據。

The presence of such rows can make myisamchk struggle

這就是爲什麼我建議運行OPTIMIZE TABLE。這樣,數據會更快地追加。

UPDATE 2012年12月3日12:58 EDT

下面是一些有趣的事情,你也可以這樣做:Try setting concurrent_insert to 2。這樣,您總是追加到MyISAM表中而不檢查表中的間隙。這將大大加快INSERT,但只留下所有已知的差距。

您仍然可以使用OPTIMIZE TABLE儘早對錶格進行碎片整理。

UPDATE 2012年12月3日13:40 EDT

爲什麼不跑我的第二sugesstion

CREATE TABLE mydb.mytable_new LIKE mydb.mytable; 
ALTER TABLE mydb.mytable_new DISABLE KEYS; 
INSERT INTO mydb.mytable_new SELECT * FROM mydb.mytable; 
ALTER TABLE mydb.mytable_new ENABLE KEYS; 
ALTER TABLE mydb.mytable RENAME mydb.mytable_old; 
ALTER TABLE mydb.mytable_new RENAME mydb.mytable; 
ANALYZE TABLE mydb.mytable; 

這會給你一個想法

  • 多久OPTIMIZE TABLE需要運行
  • .MYD和需要多少?將運行OPTIMIZE TABLE

後你跑我的第二個建議後,您可以用

SELECT 
    A.mydsize,B.mydsize,A.mydsize - B.mydsize myd_diff, 
    A.midsize,B.myisize,A.myisize - B.myisize myi_diff 
FROM 
(
    SELECT data_length mydsize,index_length myisize 
    FROM information_schema.tables 
    WHERE table_schema='mydb' AND table_name='mytable' 
) A, 
(
    SELECT data_length mydsize,index_length myisize 
    FROM information_schema.tables 
    WHERE table_schema='mydb' AND table_name='mytable_new' 
) B; 

UPDATE比較它們2012年12月3日16:42 EDT

任何表ROW_FORMAT設置爲固定,每次都有分配相同長度行的奢侈。如果MyISAM表維護已刪除行的列表,則應始終選擇列表中的第一行作爲插入數據的下一行。沒有必要遍歷整個列表,直到找到具有足夠長度的合適的行間隙。每個刪除的行都快速附加在DELETE之後。每個INSERT將選擇已刪除行的第一行。

我們可以承擔這些事情,因爲MyISAM tables can do concurrent inserts。爲了使用該功能,通過concurrent_insert選項供,插入到MyISAM表必須能夠檢測的三(3)的事情之一:

  1. 刪除的行名單的存在,因此從選擇列表
    • ROW_FORMAT =動態:刪除的行的所有行列表中的相同長度
  2. 由於沒有刪除清單的:每行具有不同的長度
  3. ROW_FORMAT =固定刪除的行的列表行,因此附加
  4. 旁路檢查刪除的行的列表的存在(設置concurrent_insert至2)

爲了檢測#1是最快的可能,MyISAM表的ROW_FORMAT必須固定。如果它是動態的,則很有可能需要遍歷列表。

+0

我想知道沒有優化表(去碎片)會發生什麼我的表是非常大的,優化可能會持續太多時間,我感興趣,因爲我在答案中解釋如果記錄將**重用* *只刪除它們並使用LOAD DATA添加新記錄? – Michael

+0

+1,自我解釋的答案。基於你的更新(2012-12-03 12:50 EDT)我明白'myisamchk'/OPTIMIZE會很困難,如果LOAD DATA在試圖重用數據時會遇到困難,如果它重用了所有數據沒有去除碎片的過程。此外,我有幾種類型的MYISAM表「Dynamic」和「Fixed」(我已經更新了這個問題),'Fixed'行格式會發生什麼? – Michael

+0

當然,INSERT到一個'Fixed'表中應該比'Dynamic'表稍快一些。此外,固定表中的行間隙應該更快填充,因爲所有行的長度都是相同的。恕我直言,消除了需要掃描刪除的行列表理想的長度。 – RolandoMySQLDBA