从 MySql 5.7 升级到 8 后,Redmine 查询非常慢

Redmine query is very slow after upgrading from MySql 5.7 to 8

提问人:Kushal Singh 提问时间:8/28/2023 最后编辑:Kushal Singh 更新时间:10/17/2023 访问量:213

问:

最近,我们将 Redmine 的 MySql 版本从 5.7 升级到 8.0.32。升级后,MyPage 查询需要很长时间才能执行(大约 1 分钟)。以前在 5.7 版中,它曾经在几秒钟内执行。

在最初的研究中,MySql 8 使用派生的查询优化概念,因此在 5.7 和 8 中解释查询的逻辑是不同的。

Redmine 版本:4.1.1.stable(在最新的 redmine 版本 5.0.5 上尝试过,但遇到了同样的问题。此外,所有适当的索引也已完成)

MyPage查询:

SELECT
  issues.id AS t0_r0,
  issues.tracker_id AS t0_r1,
  issues.project_id AS t0_r2,
  issues.subject AS t0_r3,
  issues.description AS t0_r4,
  issues.due_date AS t0_r5,
  issues.category_id AS t0_r6,
  issues.status_id AS t0_r7,
  issues.assigned_to_id AS t0_r8,
  issues.priority_id AS t0_r9,
  issues.fixed_version_id AS t0_r10,
  issues.author_id AS t0_r11,
  issues.lock_version AS t0_r12,
  issues.created_on AS t0_r13,
  issues.updated_on AS t0_r14,
  issues.start_date AS t0_r15,
  issues.done_ratio AS t0_r16,
  issues.estimated_hours AS t0_r17,
  issues.parent_id AS t0_r18,
  issues.root_id AS t0_r19,
  issues.lft AS t0_r20,
  issues.rgt AS t0_r21,
  issues.is_private AS t0_r22,
  issues.position AS t0_r23,
  issues.remaining_hours AS t0_r24,
  issues.story_points AS t0_r25,
  issues.closed_on AS t0_r26,
  issue_statuses.id AS t1_r0,
  issue_statuses.name AS t1_r1,
  issue_statuses.is_closed AS t1_r2,
  issue_statuses.position AS t1_r3,
  issue_statuses.default_done_ratio AS t1_r4,
  projects.id AS t2_r0,
  projects.name AS t2_r1,
  projects.description AS t2_r2,
  projects.homepage AS t2_r3,
  projects.is_public AS t2_r4,
  projects.parent_id AS t2_r5,
  projects.created_on AS t2_r6,
  projects.updated_on AS t2_r7,
  projects.identifier AS t2_r8,
  projects.status AS t2_r9,
  projects.lft AS t2_r10,
  projects.rgt AS t2_r11,
  projects.inherit_members AS t2_r12,
  projects.default_version_id AS t2_r13,
  projects.default_assigned_to_id AS t2_r14
FROM
  issues
  INNER JOIN projects ON projects.id = issues.project_id
  INNER JOIN issue_statuses ON issue_statuses.id = issues.status_id
  LEFT OUTER JOIN enumerations ON enumerations.id = issues.priority_id
WHERE
  (projects.status <> 9
  AND EXISTS (
    SELECT 1
    FROM enabled_modules em
    WHERE em.project_id = projects.id AND em.name='issue_tracking'
  ))
  AND (
    issues.status_id IN (SELECT id FROM issue_statuses WHERE is_closed=FALSE)
    AND issues.assigned_to_id IN ('1051', '2643')
    AND projects.status IN ('1')
  )
ORDER BY
  enumerations.position DESC,
  issues.updated_on DESC,
  issues.id DESC
LIMIT 10;

MySQL 8.0.32 解释

编号 select_type 桌子 分区 类型 possible_keys 我? key_len 裁判 过滤 额外
1 简单 issue_statuses 主要 19 100 使用临时;使用文件排序
1 简单 issue_statuses eq_ref 主要,index_issue_statuses_on_is_closed 主要 4 deermine.issue_statuses.id 1 89.47 使用where
1 简单 100 在哪里使用;使用连接缓冲区(哈希连接)
1 简单 项目 eq_ref 主要 主要 4 .project_id 1 9 使用where
1 简单 问题 裁判 issues_project_id,index_issues_on_status_id,index_issues_on_assigned_to_id issues_project_id 4 .project_id 1917 0.03 使用where
1 简单 枚举 eq_ref 主要,index_enumerations_on_id_and_type 主要 4 deermine.issues.priority_id 1 100
2 物化 他们 enabled_modules_project_id 3545 10 使用where

MySQL 5.7 解释

编号 select_type 桌子 分区 类型 possible_keys 我? key_len 裁判 过滤 额外
1 主要 问题 范围 issues_project_id,index_issues_on_status_id,index_issues_on_assigned_to_id index_issues_on_assigned_to_id 5 2560 100 使用索引条件;使用临时;使用文件排序
1 主要 issue_statuses eq_ref 主要,index_issue_statuses_on_is_closed 主要 4 deermine.issues.status_id 1 89.47 使用where
1 主要 issue_statuses eq_ref 主要 主要 4 deermine.issues.status_id 1 100
1 主要 枚举 eq_ref 主要,index_enumerations_on_id_and_type 主要 4 deermine.issues.priority_id 1 100
1 主要 项目 eq_ref 主要 主要 4 deermine.issues.project_id 1 9 使用where
2 依赖子查询 他们 裁判 enabled_modules_project_id enabled_modules_project_id 5 deermine.projects.id 5 10 使用where

如您所见,在 5.7 中,所有行都在单个查询中被拉取,而在 8.0.32 中,所有行都是在多个查询中被拉取的。

有什么办法解决这个问题吗?

MySQL 的ruby-on-rails redmine mysql-5.7 mysql-8.0

评论

0赞 danblack 8/28/2023
你能在你的问题中包含输出吗?我在这里找到了问题结构EXPLAIN {query}
0赞 Aleksandar Pavić 8/28/2023
查看其他一些与 mysql 性能相关的帖子,例如 stackoverflow.com/questions/62469293/...
0赞 Hammad Ahmed khan 8/28/2023
检查以下几点 分析查询执行计划。确保正确的索引。查看 MySQL 配置。使用最新的 Redmine 版本。优化数据库。
0赞 Kushal Singh 8/28/2023
@danblack,说明中添加了解释查询。

答:

3赞 Kushal Singh 8/31/2023 #1

我们通过关闭 MySQL 8 optimizer_switch中的“具体化”开关来解决此问题。关闭具体化开关后,SQL 不会为存在条件的位置创建临时表,从而加快查询的执行速度。

执行时间从 1+ 分钟下降到不到一毫秒。

评论

0赞 ron 10/17/2023
这解决了我们的 CPU 一直达到 100%,但我们仍然看到很多缓慢的查询,我们在 explain 命令中注意到,它没有使用 PRIMARY/SUBQUERY,而是在选择类型列中使用 SIMPLE,您是否对 mysql 优化器进行了任何其他更改?
1赞 Arie S. 10/17/2023 #2

我们遇到了同样的问题,我们在optimizer_switch进行了更改,但它只解决了部分问题。materialization=off

之后,我们在 MySQL 8 中设置并得到了与 MySQL 5.7 中完全相同的执行计划。materialization=on,semijoin=off