【问题标题】:MySQL query slowing down until restartMySQL查询减慢直到重新启动
【发布时间】:2011-11-07 20:30:41
【问题描述】:

我有一个位于 MySQL 5.5 数据库 (INNODB) 之上的服务。该服务有一个后台作业,应该每周左右运行一次。在高层次上,后台作业执行以下操作:

  1. 在一个事务中进行一些初始数据库读取和写入
  2. 在一个事务中使用一组参数执行 UMQ(如下所述)。
    • 如果没有返回记录,我们就完成了!
  3. 处理来自 UMQ 的结果(这有点重,所以它在任何数据库之外完成 交易)
  4. 在一个事务中将上一步的结果写入数据库(此 写入 UMQ 查询的表,并确保 UMQ 不会再次找到相同的记录。
  5. 转到第 2 步。

UMQ - 丑陋的怪物查询:这是一个讨厌的数据库查询,它连接了一堆表,在其中几个表中的列上有条件,并且包含一个 NOT EXISTS 子查询和更多的连接和条件. UMQ 包括 ORDER BY 也有 LIMIT 1000。即使查询很糟糕,我已经尽我所能 - 所有列上都有索引过滤,并且连接都在外键关系上。

我确实希望 UMQ 很重并且需要一些时间,这就是它在后台作业中执行的原因。但是,我看到的是性能迅速下降,直到最终导致我的服务超时(10 次迭代后可能会慢 50 倍)。

首先我认为是因为UMQ查询的数据发生了变化(见上面的步骤4),但不是因为如果我从慢查询日志中取出最后一个查询(导致超时的那个)并执行我自己直接得到了相同的行为,直到我重新启动 MySQL 服务。在重新启动对完全相同的数据进行精确查询后,在重新启动前花费了 >30 秒的时间现在花费了

另外,使用question 中描述的技巧,我可以看到查询在重新启动后扫描了大约 60K 行,而不是之前的 18M 行。 EXPLAIN 告诉我应该扫描大约 10K 行,并且 EXPLAIN 的结果总是相同的。没有其他进程同时访问数据库,慢查询日志中的 lock_time 始终为 0。重启前后的 SHOW ENGINE INNODB STATUS 没有给我任何提示。

所以最后的问题是:有人知道我为什么会看到这种行为吗?我该如何进一步分析呢?

我觉得我需要以某种方式对 MySQL 进行不同的配置,但我已经疯狂地搜索和测试,但没有想出任何有影响的东西。

【问题讨论】:

  • 您可以使用profiling 运行查询吗?
  • 您要关闭交易吗?有限制的查询是否在每个循环中使用递增的偏移量?
  • @Michael Mior:好主意 - 我会玩一些分析并用我的发现更新问题。
  • @Darhazer:是的,我已经非常仔细地检查了我是否提交了交易。通过检查我的应用程序代码和检查 MySQL 常规日志。不,不使用递增偏移量 - 查询的数据以这样的方式更改,以至于在下一次迭代期间找不到它。

标签: mysql database


【解决方案1】:

原来我看到的行为是 MySQL 优化器如何使用 InnoDB 统计信息来决定执行计划的结果。 This article 让我走上了正轨(尽管它并没有完全讨论我的问题)。我从中学到的最重要的事情是 MySQL 在启动时计算统计信息,然后每隔一段时间计算一次。然后使用此统计信息来优化查询。

按照我设置测试数据的方式,表 T 在第 4 步中完成了大多数写入,一开始是空的。在每次迭代之后,T 将包含越来越多的记录,但 InnoDB 统计信息尚未更新以反映这一点。因此,MySQL 优化器总是为 UMQ 选择一个执行计划(包括一个带有 T 的 JOIN),当 T 为空时效果很好,但记录越多越糟糕T 包含。

为了验证这一点,我在每次执行 UMQ 之前添加了一个 ANALYZE TABLE T; 并且快速降级消失了。没有闪电性能,但可以接受。我还看到离开数据库半小时左右(可能会更短,但至少超过几分钟)将使 InnoDB 统计信息自动刷新。

在实际场景中,UMQ 中涉及的表的索引基数的相对差异看起来会非常不同,并且不会快速变化,因此我决定我真的不需要对此做任何事情。

【讨论】:

    【解决方案2】:

    非常感谢您的分析和回答。在 mariadb 10.1 和 bacula server 9.4 (debian buster) 上的 ci 期间,我已经搜索了几天这个问题。

    情况是,在 CI 周期中全新安装服务器后,前两个测试(备份和还原)在未重新启动的 mariadb 服务器上运行顺利,只有第三个测试显示一个特定的 UMQ 花费了大约 20 分钟(在从大约 30k 行的表中恢复过程)。

    除非重新启动 mardiadb 服务器或分析表,否则问题不会消失。 ANALYZE TABLE 或重启改变了字段的基数和内部查询处理,完全按照链接文章中的说明。

    【讨论】:

      猜你喜欢
      • 2012-06-11
      • 1970-01-01
      • 2019-05-14
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多