对于名为的 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;
无论哪种情况,表最终都没有碎片。
试试看 !!!
更新 2012-12-03 12:50 EDT
如果您担心行是否在批量 INSERT 中通过 重用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 存储引擎将不断检查每个删除的行长度,以查看下一组要插入的数据是否适合。如果传入的数据无法放入任何已删除的行,则追加新的行数据。
这种行的存在可以使myisamchk
斗争。
这就是我推荐跑步的原因OPTIMIZE TABLE
。这样,数据将被更快地附加。
更新 2012-12-03 12:58 EDT
您还可以做一些有趣的事情:尝试将 concurrent_insert 设置为 2。这样,您总是在不检查表中的间隙的情况下追加到 MyISAM 表。这将显着加快 INSERT,但不理会所有已知的空白。
您仍然可以尽早使用OPTIMIZE TABLE
.
更新 2012-12-03 13:40 EDT
为什么不运行我的第二个建议
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
运行后和.MYI
会小多少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;
更新 2012-12-03 16:42 EDT
任何 ROW_FORMAT 设置为固定的表都可以每次都分配相同长度的行。如果 MyISAM 表维护一个已删除行的列表,则应始终选择列表中的第一行作为插入数据的下一行。在找到具有足够长度的合适行间隙之前,无需遍历整个列表。每个删除的行都会快速附加到DELETE
. 每个 INSERT 都会选择已删除行的第一行。
我们可以假设这些事情,因为MyISAM 表可以进行并发插入。为了通过concurrent_insert选项使用此功能,在 MyISAM 表中的 INSERT 必须能够检测到以下三 (3) 项之一:
- 存在已删除行的列表,因此从列表中选择
- Row_Format=Dynamic :已删除行的列表,每行的长度不同
- Row_Format=Fixed :所有行长度相同的已删除行列表
- 缺少已删除行的列表,因此追加
- 绕过检查是否存在已删除行的列表(将concurrent_insert设置为 2)
为了使检测#1 尽可能快,MyISAM 表的 row_format 必须是固定的。如果是动态的,很有可能需要遍历列表。