【问题标题】:How to optimize an "optimize" MYSQL query that takes a lot of time如何优化需要大量时间的“优化”MYSQL 查询
【发布时间】:2019-07-21 08:19:10
【问题描述】:

我有一个表 (innodb),每周有 100 万个新插入 (20GB)。我只需要 1 周的数据,所以我在 7 天后删除了它,所以每天我们删除大约 3GB 并插入 3GB 新数据。该表已经与其他表位于不同的数据库中。

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

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

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

【问题讨论】:

  • 你的 MySQL 版本是多少?你有足够的可用硬盘空间吗? Optimize 不应该冻结你的整个数据库。此外,虽然在删除时不释放,但它会重用空间。因此,如果您每天删除,它应该保持在大约 8 天的大小,它不会下降到 7 天的大小,白天会增长到 8 天的大小,删除时会回落到 7 天的大小. (如果您每周删除,它应该保持在大约 14 到 15 天的大小)。你测试过/那会是个问题吗?
  • 一个建议here,但从未使用过。来自this one - 尝试删除索引,优化然后重新创建
  • 你确定优化真的有必要吗? IIRC 然后 InnoDB 将空间标记为在删除后可重用,因此新添加的行将插入该空间。所以运行优化器的唯一结果是被 InnoDB 标记为空闲的区域也会在系统本身上释放。如果您不运行该优化脚本,您是否检查过您的数据库使用量是否真的在增长,比如说一个星期。
  • MySQL 版本为 5.0.11。有足够的磁盘空间,但需要定期运行优化,因为 InnoDB 在某种程度上不会重用它在删除后没有释放的磁盘空间。数据库的大小不断增长。刚刚尝试再次运行它,花了55分钟。表/数据库(我们将该表移动到单独的数据库)大小为 20GB // 400k 行。更新mysql有帮助吗?还有其他想法吗?
  • 表里到底是什么?听起来平均行是 20KB;这是异常大的,必须涉及“非记录”存储。 可能有更好的方法来处理所涉及的TEXT/BLOB(s)。

标签: mysql database innodb database-optimization


【解决方案1】:

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

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

然后DROP PARTITION nightly;这比使用DELETE 快得多,并且无需使用OPTIMIZE

一定要有innodb_file_per_table=ON

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

详情请看:http://mysql.rjweb.org/doc.php/partitionmaint

请注意,每个PARTITION 实际上是一个单独的表,因此DROP PARTITION 实际上是一个删除表。

应该有10个分区:

  • 1 个起始表,以避免在按DATETIME 分区时出现故障开销。
  • 每天7个分区
  • 多出 1 天,因此会有 完整 7 天的价值。
  • 1 个空的future 分区,以防您的夜间脚本无法运行。

【讨论】:

  • 对不起。 PARTITIONing 直到 5.1 才可用。 5.0 已经十年了。是时候升级了!你等待升级的时间越长,它就越难。从那以后,先后有 5.1、5.5、5.6、5.7、8.0。
  • 哎哟! 5.0.11 日期为 2005-08-06。最终版本 (5.0.96) 可追溯到 2012-03-21 。
  • 我们在另一台数据库服务器上运行 MariaDB-10.2.25,可以将它移到那里,看来这个版本将支持 PARTITIONing
  • 是的,MariaDB 10.2 有PARTITIONing;我的链接可以正常工作。 (MariaDB 在 5.1 左右分叉了 MySQL,并从那时起保持了很多兼容性。)
【解决方案2】:

由于你有一个没有PARTITIONing的古董版,这里有另一个解决方案:

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

这不会消除OPTIMIZE 问题,但会

  • 使用更少的磁盘空间。
  • 更快(因为需要挖掘的数据更少)。

但是,如前所述,InnoDB 会在一定程度上清理可用空间。我怀疑优化后表格不会超过 2 倍?通常情况下,一开始没有可用空间的 BTree 在大量流失后会降级到大约 69%。但它保持在这个比例。

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

【讨论】:

  • 我们需要使用该列上的 FULLTEXT 索引来搜索电子邮件,这在压缩数据时将不起作用。我认为迁移到能够使用分区的最新数据库解决方案将保留全部功能并仍然解决问题
  • @DeveloperJano - 真; FT 需要未压缩的数据。 (而您与 ROW_FORMAT=COMPRESSED 相差 许多 个版本。)
【解决方案3】:

MySQL 不是为该卷设计的... 尝试使用 AWS RedShift 之类的仓库数据库引擎(列引擎),它会再次感觉到 4 mb 的数据库 :) 如果不能使用,可以安装postgres并添加压缩柱状表的插件(应该类似于redshift)

【讨论】:

  • 我不同意。每 插入一百万行对 MySQL 来说不是问题。太字节的数据也不是。问题可能是索引不佳或编写效率低下的查询。至于 DW,必须手动构建和维护一个大型 DW 应用程序的汇总表,在 MySQL 上运行良好。
  • 根据一项研究,7% 的 MySQL 表大于 700 万行。
猜你喜欢
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-14
  • 2013-11-18
  • 2014-02-15
相关资源
最近更新 更多