如何优化花费大量时间的 "optimize" MYSQL 查询

How to optimize an "optimize" MYSQL query that takes a lot of time

我有一个 table (innodb),每周有 100 万个新插入 (20GB)。我只需要 1 周的数据,所以我会在 7 天后删除它,所以每天我们删除大约 3GB 并插入 3GB 新数据。 table 已经在一个单独的数据库中。

问题是磁盘 space 仅在优化查询后才被释放,因此我们 运行 每隔几周在晚上进行一次。它可以工作,但需要 30 分钟并冻结整个数据库服务器,而不仅仅是特定的数据库。

有什么方法可以更快地优化?

如果我们 运行 每次删除数据时都进行优化,是否会比 运行 每隔几周进行一次优化更快?我认为当只需要从磁盘中删除 3GB 的已删除行时 运行 它可能会更快,如果我们 运行 它在 20 天后它是 60GB。那正确吗?还有另一种优化优化的方法吗?

与其担心加速 OPTIMIZE TABLE,不如让我们摆脱对它的需求。

PARTITION BY RANGE(TO_DAYS(...)) ...

然后 DROP PARTITION 每晚;这比使用 DELETE 快得多,并且避免了 OPTIMIZE.

的需要

一定要innodb_file_per_table=ON.

同样每晚,使用 REORGANIZE PARTITIONfuture 分区变成明天的分区和一个新的空分区。

详情在这里:http://mysql.rjweb.org/doc.php/partitionmaint

请注意,每个 PARTITION 实际上是一个单独的 table,因此 DROP PARTITION 实际上是一个下降 table。

应该有 10 个分区:

  • 1 个启动器 table 以避免按 DATETIME 分区时出现故障的开销。
  • 7 个日常分区
  • 额外 1 天,这样就会有 完整 7 天的价值。
  • 1 个空 future 分区,以防万一您的夜间脚本无法 运行。

MySQL 不是为该卷设计的... 尝试像 AWS RedShift 这样的仓库数据库引擎(列式引擎),它会再次感觉到一个 4 MB 的数据库:) 如果不会用,可以安装postgres,添加compressed columnar tables的插件(应该和redshift类似)

既然你有一个没有PARTITIONing的古董版本,这里有另一个解决方案:

  • 压缩 html 并存储到 BLOB(而不是 TEXT)。
  • 在客户端进行压缩和解压缩。
  • 此技术将减少磁盘占用空间 3:1。

这不会消除 OPTIMIZE 问题,但会

  • 使用更少的磁盘space。
  • 更快(因为要收集的数据更少)。

但是,正如已经提到的,InnoDB 在某种程度上清理了免费 space。我怀疑 table 在优化后不会增长超过 2 倍?通常情况下,一开始没有空闲 space 的 BTree 在大量流失后会降级到大约 69%。但随后它保持在那个比例。

电子邮件、HTML、文本、代码——所有这些都可以通过任何像样的压缩库(zlib、PHP 的 compress() 等压缩 3:1 ).大多数图像格式和 pdf 已经压缩;他们不会从第二次压缩中受益。