数据库
首页 > 数据库> > mysql-删除后LOAD DATA回收磁盘空间

mysql-删除后LOAD DATA回收磁盘空间

作者:互联网

我有一个由MYISAM表组成的数据库架构,我有兴趣不时从某些表中删除旧记录.

我知道delete不会回收内存空间,但是正如我在DELETE命令的描述中发现的那样,插入可能会重用已删除的空间

在MyISAM表中,已删除的行保留在链接列表中,随后的INSERT操作将重用旧的行位置.

我是否对LOAD DATA命令还重用已删除的空间感兴趣?

更新

我也有兴趣如何回收索引空间?

更新2012-12-03 23:11

根据从@RolandoMySQLDBA收到的答案提供了一些更多信息

执行以下建议的查询后,对于需要重用或回收空间的不同表,我得到了不同的结果:

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

>动态

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

>固定

更新2012-12-09 08:06

当且仅当行格式是固定的或(行格式是动态的,并且删除的行具有完全相同的大小)时,LOAD DATA才会重用以前删除的空间(我已经通过运行短脚本对其进行了检查).

似乎如果row_format是动态的,则对每条记录进行完整的删除列表查找,并且如果未找到确切的行大小,则不使用删除的记录,并且表内存使用量将增加,另外需要LOAD DATA将花费更多时间来导入记录.

除了这里给出的答案外,我将不作任何介绍,因为它完美地描述了所有过程.

解决方法:

对于名为mydb.mytable的MySQL表,只需运行以下命令:

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

如果您担心是否通过LOAD DATA INFILE在大容量INSERT上重用行,请注意以下几点:

当您创建MyISAM表时,我假设默认的行格式是动态的.您可以检查其中之一

SHOW CREATE TABLE mydb.mytable\G

要么

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

由于表的行格式是动态的,因此分散的行具有各种大小. MyISAM存储引擎将一直检查每个删除的行的长度,以查看是否要插入下一组数据.如果输入的数据不能容纳在任何已删除的行中,则将附加新的行数据.

The presence of such rows can make myisamchk struggle.

这就是为什么我建议运行OPTIMIZE TABLE的原因.这样,数据将被更快地附加.

更新2012-12-03 12:58 EDT

您也可以执行以下操作:Try setting concurrent_insert to 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会缩小多少

运行第二条建议后,您可以将它们与

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 tables can do concurrent inserts.为了使该功能通过concurrent_insert选项可用,将INSERT插入MyISAM表必须能够检测三(3)件事之一:

>存在已删除行的列表,因此可以从列表中进行选择

> Row_Format = Dynamic:删除的行的列表,每行的长度不同
> Row_Format =固定:所有行的长度都相同的已删除行的列表

>缺少删除行的列表,因此追加
>绕过检查是否存在已删除行的列表(将concurrent_insert设置为2)

为了使检测#1尽可能快,必须将MyISAM表的row_format固定.如果是动态的,则很有可能需要遍历列表.

标签:load-data-infile,mysql
来源: https://codeday.me/bug/20191031/1976695.html