MySQL:为MyISAM表减少ibdata文件大小

4
我的问题与这个问题非常相似,并且包含了一个针对InnoDB引擎表的好答案:https://dba.stackexchange.com/questions/8982/is-there-any-best-way-to-reduce-the-size-of-ibdata-in-mysql/8983#8983。我注意到删除模式不会缩小ibdata文件,所以我寻找一种方法来配置数据库,使得在删除模式后可以减少大小。我发现许多链接都在谈论InnoDB和保存每个文件的表格的方式,因此.frm文件本身将包含表格数据并减小文件大小。但是对于MyISAM表格(超过5G表格大小),会发生什么呢?

1
有很多帖子讨论了ibdata。顺便说一下,ibdata是针对innodb而不是myisam的。myd是针对myisam的。 - Jacob
2个回答

4

ibdata1和MyISAM是互斥的。

首先,您应该统计使用这两种存储引擎的表的数量:

SELECT COUNT(1) EngineCount,engine
FROM information_schema.tables
WHERE table_schema NOT IN ('information_schema','performance_schema','mysql')
GROUP BY engine;

如果有一些表是InnoDB类型:

执行清理InnoDB的操作

如果您只有MyISAM表而没有InnoDB表:

首先,消除任何InnoDB痕迹 按照以下步骤进行:

STEP01) 将以下内容添加到my.cnf中

[mysqld]
skip-innodb

步骤02) service mysql restart

步骤03) rm -f /var/lib/mysql/ibdata1 /var/lib/mysql/ib_logfile*

完成这些步骤后,您可以执行以下操作压缩每个MyISAM表:

对于MyISAM类型的表mydb.mytable,只需运行以下命令之一:

  • OPTIMIZE TABLE mydb.mytable;
  • ALTER TABLE mydb.mytable ENGINE=MyISAM; ANALYZE TABLE mydb.mytable;

如果您想要碎片整理所有MyISAM表,这是一个shell脚本...

MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
SQL="SELECT CONCAT('OPTIMIZE TABLE ',table_schema,'.',table_name,';') "
SQL="${SQL} FROM information_schema.tables "
SQL="${SQL} WHERE engine='MyISAM' AND table_schema NOT IN "
SQL="${SQL} ('information_schema','performance_schema','mysql')"
mysql ${MYSQL_CONN} -ANe"${SQL}" > GlobalMyISAMOptmizeTable.sql
less GlobalMyISAMOptmizeTable.sql

如果你在视觉上信任这个脚本,那么就直接运行它。

mysql ${MYSQL_CONN} < GlobalMyISAMOptmizeTable.sql

来试试吧!

更新 2012-07-25 09:52 EDT

我想澄清一下关于压缩 MyISAM 的建议之一。

我之前说过:

  • OPTIMIZE TABLE mydb.mytable;
  • ALTER TABLE mydb.mytable ENGINE=MyISAM; ANALYZE TABLE mydb.mytable;

这些命令在机械上是相同的。 OPTIMIZE TABLE 对 MyISAM 表进行碎片整理,然后运行 ANALYZE TABLE 来计算最新的索引统计信息。

从机械的角度来看,这就是 ALTER TABLE mydb.mytable ENGINE=MyISAM; 所做的事情:

CREATE TABLE mydb.mytabletmp LIKE mydb.mytable;
INSERT INTO mydb.mytabletmp SELECT * FROM mydb.mytable;
ALTER TABLE mydb.mytable RENAME mydb.mytablezap;
ALTER TABLE mydb.mytabletmp RENAME mydb.mytable;
DROP TABLE mydb.mytablezap;

非常建设性的回答,谢谢! - Michael
为什么我需要修改表格mydb.mytable ENGINE=MyISAM;,如果它已经是MyISAM了呢? - Michael

2

如前所述,MyISAM 不应该使用 ibdata。请问您在 my.cnf 中或 MySQL shell 中的 innodb 设置是什么?您可以输入以下命令:

    SHOW VARIABLES LIKE "%innodb%";

这些变量被设置了吗?

    innodb_data_home_dir
    innodb_data_file_path

如果您完全没有使用INNODB,您应该能够安全地删除ibdata和ib_logfile(s),然后重新启动MySQL。但通常情况下,在未先删除表的情况下删除这些文件会导致问题。 参见如何在MySQL中缩小/清除ibdata1文件 如果您有一个大于5G的MyISAM表,建议您仍然使用INNODB(任何超过4G的表)。 要进行故障排除,您可以尝试添加:
    skip-innodb 

如果您完全不使用INNODB,则在my.cnf中进行配置。


我不能将表更改为INNODB,因为它会降低读取性能,我有很多读取操作和少量写入操作。 - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接