對於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)的事情之一:
- 刪除的行名單的存在,因此從選擇列表
- ROW_FORMAT =動態:刪除的行的所有行列表中的相同長度
- 由於沒有刪除清單的:每行具有不同的長度
- ROW_FORMAT =固定刪除的行的列表行,因此附加
個
- 旁路檢查刪除的行的列表的存在(設置concurrent_insert至2)
爲了檢測#1是最快的可能,MyISAM表的ROW_FORMAT必須固定。如果它是動態的,則很有可能需要遍歷列表。
我想知道沒有優化表(去碎片)會發生什麼我的表是非常大的,優化可能會持續太多時間,我感興趣,因爲我在答案中解釋如果記錄將**重用* *只刪除它們並使用LOAD DATA添加新記錄? – Michael
+1,自我解釋的答案。基於你的更新(2012-12-03 12:50 EDT)我明白'myisamchk'/OPTIMIZE會很困難,如果LOAD DATA在試圖重用數據時會遇到困難,如果它重用了所有數據沒有去除碎片的過程。此外,我有幾種類型的MYISAM表「Dynamic」和「Fixed」(我已經更新了這個問題),'Fixed'行格式會發生什麼? – Michael
當然,INSERT到一個'Fixed'表中應該比'Dynamic'表稍快一些。此外,固定表中的行間隙應該更快填充,因爲所有行的長度都是相同的。恕我直言,消除了需要掃描刪除的行列表理想的長度。 – RolandoMySQLDBA