叙述

【摘要】 如果您的应用程序正在对 MySQL 数据库执行大量删除和更新,那么您的 MySQL 数据文件很可能是碎片化的。 这将导致大量未使用的空间,并且还可能影响性能。 因此,强烈建议您持续对 MySQL 表进行碎片整理。

如果您的应用程序正在对 MySQL 数据库执行大量删除和更新,那么您的 MySQL 数据文件很可能是碎片化的。

这将导致大量未使用的空间,并且还可能影响性能。

因此,强烈建议您持续对 MySQL 表进行碎片整理。

本教程解释了如何优化 MySQL 以对表进行碎片整理并回收未使用的空间。


1. 确定优化表

第一步是确定您的 MySQL 数据库是否有碎片。

连接到您的 MySQL 数据库,并执行以下查询,这将显示每个表中有多少未使用的空间可用。

mysql> use tiamo;

mysql> select table_name,
round(data_length/1024/1024) as data_length_mb, 
round(data_free/1024/1024) as data_free_mb 
 from information_schema.tables 
 where round(data_free/1024/1024) > 500 
 order by data_free_mb;

+------------+----------------+--------------+
| table_name | data_length_mb | data_free_mb |
+------------+----------------+--------------+
| BENEFITS   |           7743 |         4775 |
| DEPARTMENT |          14295 |        13315 |
| EMPLOYEE   |          21633 |        19834 |
+------------+----------------+--------------+

在上面的输出中:

  • 这将显示具有最少 500MB 未使用空间的所有表的列表。正如我们在上面看到的,在这个例子中,有 3 个表的未使用空间超过 500MB。
  • data_length_mb 列显示总表大小(以 MB 为单位)。例如,EMPLOYEE 表大小约为 21GB。
  • data_free_mb 列显示该特定表中未使用的总空间。例如,EMPLOYEE 表中有大约 19GB 的未使用空间。
  • 所有这三个表(EMPLOYEE、DEPARTMENT 和 BENEFITS)都非常碎片化,需要对其进行优化以回收未使用的空间。

从文件系统级别,您可以看到各个表文件的大小,如下所示。

文件大小将与您在上述输出中的“data_length_mb”列下看到的相同。

# ls -lh /var/lib/mysql/tiamo/
..
-rw-rw----. 1 mysql mysql  7.6G Apr 23 10:55 BENEFITS.MYD
-rw-rw----. 1 mysql mysql   14G Apr 23 12:53 DEPARTMENT.MYD
-rw-rw----. 1 mysql mysql   22G Apr 23 12:03 EMPLOYEE.MYD
..

在此示例中,EMPLOYEE.MYD 文件在文件系统级别占用了大约 22GB,但其中有很多未使用的空间。如果我们优化这个表,这个文件的大小应该会急剧下降。


2. 使用 OPTIMIZE TABLE 命令进行碎片整理

有两种方法可以优化表。

第一种方法是使用优化表命令,如下所示。

以下示例将优化 EMPLOYEE 表。

mysql> use tiamo;

mysql> OPTIMIZE TABLE EMPLOYEE;

您还可以在单个命令中优化多个表,如下所示。

mysql> OPTIMIZE TABLE EMPLOYEE, DEPARTMENT, BENEFITS

关于优化表要记住的几点:

  • 可以为 InnoDB 引擎、MyISAM 引擎或 ARCHIVE 表执行优化表。
  • 对于 MyISAM 表,它会分析表,对相应的 MySQL 数据文件进行碎片整理,并回收未使用的空间。
  • 对于 InnoDB 表,优化表将简单地执行一个更改表来回收空间。
  • 如果您有索引,它还会重新搜索索引页面,并更新统计信息。

优化时MySQL会为该表创建一个临时表,优化后删除原表,并将该临时表重命名为原表。

上述优化中,EMPLOYEE表为MyISAM表。

对于此示例,在优化之前,您将看到表的以下 .MYD 文件。

# ls -lh /var/lib/mysql/tiamo/EMPLOYEE.*
-rw-rw----。1 mysql mysql 22G Apr 23 12:03 EMPLOYEE.MYD

当“OPTIMIZE TABLE”命令运行时,你可以看到它已经为这个表创建了一个扩展名为.TMD的临时文件。这个临时文件的大小将不断增长,直到优化表运行。

# ls -lh /var/lib/mysql/tiamo/EMPLOYEE.*
-rw-rw----。1 mysql mysql 22G Apr 23 12:03 EMPLOYEE.MYD
-rw-rw----。1 mysql mysql 500M Apr 23 14:10 EMPLOYEE.TMD

优化表命令完成后,您将看不到临时表。相反,您将看到经过优化且文件大小减小的原始 EMPLOYEE.MYD 文件。

# ls -lh /var/lib/mysql/tiamo/EMPLOYEE.*
-rw-rw----. 1 mysql mysql    2G Apr 23 14:20 EMPLOYEE.MYD

3. 使用 mysqlcheck 命令进行碎片整理

优化表的第二种方法是使用 mysqlcheck 命令,如下所示。

以下示例将优化 DEPARTMENT 表。您将从 Linux 提示符(而不是 MySQL 提示符)执行此命令。

# mysqlcheck -o tiamo DEPARTMENT -u root -pMySQLSecretPwd99
thegeekstuff.DEPARTMENT  OK

注意:mysqlcheck 命令在内部使用“OPTIMIZE TABLE”命令。

在上面的例子中:

  • mysqlcheck 是从 Linux 提示符执行的命令。
  • -o 选项是指示 mysqlcheck 应该执行“优化表”操作。
  • thegeekstuff 是数据库
  • DEPARTMENT是geekstuff数据库里面应该优化的表
  • -u root 表示mysqlcheck命令应该使用“root”作为mysql用户连接
  • -p 表示mysql的root账户密码。请注意 -p 选项和密码之间没有空格。

除了优化之外,您还可以使用mysqlcheck 命令来检查、分析和修复 mysql 数据库中的表。


4.对所有表或所有数据库进行碎片整理

如果要优化特定 MySQL 数据库中的所有表,请使用以下命令。

以下命令将优化位于 geekstuff 数据库中的所有表。

mysqlcheck -o tiamo -u root -pMySQLSecretPwd99

如果您的系统上运行多个数据库,则可以使用以下命令优化系统上所有数据库下的所有表。

以下将优化您系统上的所有数据库。

mysqlcheck -o --all-databases -u root -pMySQLSecretPwd99

5.优化后

优化后,使用以下查询,检查我们在此示例中优化的三个表的总大小和未使用空间大小。

mysql> use tiamo;

mysql> select table_name,
round(data_length/1024/1024) as data_length_mb, 
round(data_free/1024/1024) as data_free_mb 
 from information_schema.tables 
 where table_name in 
 ( 'EMPLOYEE', 'DEPARTMENT', 'BENEFITS' );
 
+------------+----------------+--------------+
| table_name | data_length_mb | data_free_mb |
+------------+----------------+--------------+
| BENEFITS   |           2968 |            0 |
| DEPARTMENT |            980 |            0 |
| EMPLOYEE   |           1799 |            0 |
+------------+----------------+--------------+

正如我们从上面的输出中看到的,优化后这些表的 data_length_mb 急剧减少。此外,data_free_mb 现在为 0,因为不再有碎片。

与原始大小相比,这些表的文件大小现在要小得多。我们现在已经为这些表在文件系统级别回收了大量未使用的空间。

# ls -lh /var/lib/mysql/tiamo/
..
-rw-rw----. 1 mysql mysql    3G Apr 23 14:23 BENEFITS.MYD
-rw-rw----. 1 mysql mysql  980M Apr 23 14:30 DEPARTMENT.MYD
-rw-rw----. 1 mysql mysql    2G Apr 23 14:45 EMPLOYEE.MYD
..

在这个例子中,我们在优化这三个表后回收了大约 37GB 的未使用空间。