“表不支持优化,而是重新创建 + 分析”是什么意思?

我正在研究 MySQL 5.5,并尝试使用 OPTIMIZE TABLE查询进行索引重建。我得到了下面的错误:

表不支持优化,而是执行重新创建 + 分析

这是什么意思?MySQL 引擎不允许索引重建吗?在 MySQL 5.5引擎级别,在这个消息后面做了什么?

142469 次浏览

这真是一个信息性的信息。

您可能正在对 InnoDB表(使用 InnoDB 存储引擎而不是 MyISAM存储引擎的表)执行 OPTIMIZE。

InnoDB 不像 MyISAM 那样支持 OPTIMIZE。它有不同的作用。它创建一个空表,并将现有表中的所有行复制到该表中,然后基本上删除旧表并重命名新表,然后运行分析来收集统计信息。这是 InnoDB 能够做的最接近 OPTIMIZE 的事情。

你得到的信息基本上是 MySQL 服务器重复 InnoDB 存储引擎告诉 MySQL 服务器:

表不支持优化 是 InnoDB 存储引擎说..。

“我(InnoDB 存储引擎)不像我的朋友(MyISAM 存储引擎)那样执行 OPTIMIZE 操作。”

InnoDB 存储引擎说的是“重新创建 + 分析代替” ..。

“我已经决定执行一组 与众不同操作,这些操作将获得相同的结果。”

剪辑

在 MySQL 5.7和 MariaDB 10.3上观察到的行为需要进行准确性检查 需要强调的是,InnoDB 和 MyISAM 是两种不同的存储引擎。他们的运作方式不同。这就是为什么我们看到的信息是不同的。

我们正在向 MySQL 数据库服务器发出 DDL 语句。MySQL 服务器接收语句,执行通常的语法检查解析、标记和... ,并解析对字典中带有查找的表和列的引用。


请注意,如果您的磁盘空间不足,请不要使用此选项,因为它可能会导致您的服务器在试图重新创建非常大的表时出现故障。 —— Danny Staple

是的,注意磁盘空间的限制。以及操作在表上持有排他(阻塞)锁的时间。如果我们了解了优化器将要提出的操作; 通常对于大量数据,我选择分区,它允许在可以切换到(REPLACE)现有分区的独立表上进行操作。

根据官方支持文章: http://dev.mysql.com/doc/refman/5.5/en/optimize-table.htmlOPTIMIZE TABLE可以很好地与 InnoDB 引擎一起工作

您会注意到,优化 InnoDB 表将重新构建表结构并更新索引统计信息(类似于 ALTER TABLE)。

请记住,此消息可能只是一个信息提及,而非常重要的信息是您的查询的状态: 刚刚好!

mysql> OPTIMIZE TABLE foo;
+----------+----------+----------+-------------------------------------------------------------------+
| Table    | Op       | Msg_type | Msg_text                                                          |
+----------+----------+----------+-------------------------------------------------------------------+
| test.foo | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| test.foo | optimize | status   | OK                                                                |
+----------+----------+----------+-------------------------------------------------------------------+

更好的选择是创建一个新表,将行复制到目标表,删除实际表并重命名新创建的表。 这种方法适用于小型桌子,

最好的选择是创建具有相同属性的新表

CREATE TABLE <NEW.NAME.TABLE> LIKE <TABLE.CRASHED>;
INSERT INTO <NEW.NAME.TABLE> SELECT * FROM <TABLE.CRASHED>;

重命名 New.Name.TABLE 和 Table.Crash

RENAME TABLE <TABLE.CRASHED> TO <TABLE.CRASHED.BACKUP>;
RENAME TABLE <NEW.NAME.TABLE> TO <TABLE.CRASHED>;

下班后,好好的,删除

DROP TABLE <TABLE.CRASHED.BACKUP>;

我知道这是一个非常老的主题/问题描述,但也许可以执行一种新的方法。

我对 InnoDB 引擎表也有同样的问题。

正如“ sdesvergez”所说,尽管返回的消息另有说法,但是这个 Optimize 仍然可以工作。但我们不知道背景中真正的后果是什么。

我假设您的表不太大(小于1GB)像我的(200Mb)。

我改变了表的结构,不再使用“纯”的 InnoDB,而是使用一个分区来设置表:

CREATE TABLE IF NOT EXISTS <<schema>>.<<table name>>(
<<your tabe definition>>
) PARTITION BY KEY(<<key from table, in my case I used "day">>)
PARTITIONS 1;

这个表仍然可以用于 InnoDB 引擎,但是它现在有了一个更深层次的 Partitions 结构。

这样做之后,您就可以重新构建分区,以便对其进行优化。

重新构建将失去分配给已删除记录的空间,并且还会优化表。在我的情况下,这个过程需要10秒钟。

这样,您就不会在操作的状态中收到任何奇怪的消息。

到目前为止,我没有任何数据丢失或任何其他问题使用这种方法,但一个非常快速和有组织的表。