MyISAM 和 InnoDB 如何利用 HD 空间?

Mik*_*e B 7 mysql innodb myisam disk-space-utilization

我的 MySQL 服务器快用完了 HD 空间。我的大部分大表都使用 InnoDB 引擎(没有关键任务的原因)。为了避免可怕的删除数据库以恢复 innodb 磁盘空间响应,我想更好地了解这两个引擎如何在磁盘上存储数据。

  1. 如果我使用 MyISAM,我是否能够通过删除行来更轻松地恢复磁盘空间?除了删除/截断/空查询之外,是否还有我必须运行的命令?
  2. 假设 #1 为真:将现有的 InnoDB 表转换为 MyISAM 并以这种方式恢复空间是否可能/可行?

Rol*_*DBA 12

MySQL 对 DiskSpace 的使用是可以预见的。

information_schema 可以快速透露两个存储引擎使用了多少空间。但是,使用 innodb_file_per_table 配置 InnoDB 会好得多。这样,您可以对单个 InnoDB 表的磁盘空间进行微观管理。如果您没有 innodb_file_per_table,ibdata1 将增长并且永远不会缩小。

我写了关于一劳永逸地清理 InnoDB 的好文章。

对于 MyISAM,您需要定期运行以下其中一项:

  • OPTIMIZE TABLE myisam-tablename;
  • ALTER TABLE myisam-tablename ENGINE=MyISAM; ANALYZE TABLE myisam-tablename;

这些将压缩 MyISAM,以便 MyISAM 表组件(.MYD 和 .MYI)中没有未使用的数据和索引页

您可以使用此查询手动监控磁盘空间使用情况:

SELECT IFNULL(B.engine,'Total') "Storage Engine", CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',SUBSTR(' KMGTP',pw+1,1),'B') "Table Size" FROM (SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,SUM(data_length+index_length) TSize FROM information_schema.tables WHERE table_schema NOT IN ('mysql','information_schema','performance_schema') AND engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,(SELECT 3 pw) A ORDER BY TSize;
Run Code Online (Sandbox Code Playgroud)

这将告诉引擎存储引擎的数据和索引占用了多少空间。请注意查询末尾的子句:(SELECT 3 pw)。更改编号以生成不同单位的报告

(SELECT 0 pw) for Bytes
(SELECT 1 pw) for KiloBytes
(SELECT 2 pw) for MegaBytes
(SELECT 3 pw) for GigaBytes
(SELECT 4 pw) for TeraBytes
(SELECT 5 pw) for PetaBytes (Write me if you every get numbers this high)
Run Code Online (Sandbox Code Playgroud)

更新 2012-05-26 22:29 EDT

说到InnoDB,如果使用innodb_file_per_table,你可能会发现文件的文件大小.ibd和data_length + index_length之和是有区别的。

对于 InnoDB 表mydb.mytable,以下是您应该进行的比较:

  • 通过运行获取文件的大小 ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print %5}'
  • 从信息schemna的角度获取表的大小: SELECT data_length+index_length FROM information_schema.tables WHERE table_schema='mydb' AND table_name='mytable';
  • 如果filesize > (data_length+index_length) * 1.1, 那么你应该像这样拖动表格:ALTER TABLE mydb.mytable ENGINE=InnoDB;

这将创建一个临时表,仅将真实数据页和索引页复制到临时表中,删除原始表,并将临时表重命名回 mydb.mytable。使用一个命令即时压缩表。请在下班时间计划所有表压缩。


War*_*ner 3

MyISAM 分配给磁盘反映了实际使用的空间。如果您不使用外键、事务或 InnoDB 独有的任何其他功能,您可以轻松转换为 MyISAM。InnoDB 的写入速度更快,MyISAM 的读取速度更快。最终,我建议在任意更改存储引擎之前详细研究引擎之间的差异。

这是我过去用来释放 InnoDB 表空间的过程:

从mysql innodb中删除大块数据