# private-message-topic-tracking-state.json 加载缓慢

**URL:** https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482
**Category:** Bug
**Created:** [2021年九月2日 19:16 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482 "2021-09-02T19:16:29Z")
**Posts on this page:** 14
**Page:** 2

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2021年九月8日 21:55 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/25 "2021-09-08T21:55:36Z")

</div>

哦，我明白了，这个查询会有些吃力。更新到最新版本后，能否请您从 mini\_profiler 中提取该查询，对其运行 `explain analyze` 并与我们分享结果？

在 Meta（RDS db.r6g.large 30GB）上，结果如下：

> **[El78 | explain.depesz.com](https://explain.depesz.com/s/El78)**

---

<div class="post-metadata">

### Author: ![forkythetoy](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/forkythetoy/32/199298_2.png) [@forkythetoy](https://meta.discourse.org/u/forkythetoy)
#### Post date: [2021年九月8日 22:40 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/26 "2021-09-08T22:40:28Z")

</div>

我会再尝试运行 explain analyze，但我们一直未能成功完成该查询。

---

<div class="post-metadata">

### Author: ![Hooksmith](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hooksmith/32/142826_2.png) [@Hooksmith](https://meta.discourse.org/u/Hooksmith)
#### Post date: [2021年九月8日 22:46 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/27 "2021-09-08T22:46:55Z")

</div>

更新：此提交未做任何更改。更新后数据库仍持续以超过 95% 的负载运行，并终止所有旧查询。在 beta4 版本时，该论坛的数据库负载稳定在 20-30%。我们已执行过自动清理（auto-vacuum）和模式重建索引（schema reindex）。

如何禁用此功能？单纯升级数据库实例似乎并非正确的解决方案。鉴于该查询在此更新前运行良好，问题似乎出在查询的计算方式上。

---

<div class="post-metadata">

### Author: ![forkythetoy](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/forkythetoy/32/199298_2.png) [@forkythetoy](https://meta.discourse.org/u/forkythetoy)
#### Post date: [2021年九月8日 23:07 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/28 "2021-09-08T23:07:37Z")

</div>

查询在约 21 分钟后成功完成。

> **[gs84 | explain.depesz.com](https://explain.depesz.com/s/gs84)**

另外需要注意的是，我们使用的是 PG 10.17，因为我们的输出结果似乎存在较大差异。

---

<div class="post-metadata">

### Author: ![Hooksmith](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hooksmith/32/142826_2.png) [@Hooksmith](https://meta.discourse.org/u/Hooksmith)
#### Post date: [2021年九月9日 11:24 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/29 "2021-09-09T11:24:21Z")

</div>

我们暂时通过猴子补丁修复了该问题，将所有 `*/private-messages-all/*` 路由重定向到 `*/private-messages/*`。结果是“所有收件箱”的内容与“个人”相同，但至少我们不再需要持续应对 100% 的 CPU 占用。

猴子补丁代码：

```ruby
# name: discourse-private-messages-perf-hotfix
# version: 0.0.1
# authors: 

# 前置以覆盖现有路由
Discourse::Application.routes.prepend do
  scope path: nil, constraints: { format: /(json|html|\*\/\*)/ } do
    scope "/topics", username: RouteFormat.username do
      # 将所有 */private-messages-all/* 路由重定向到 */private-messages/*（个人消息）
      # 前者开销大，后者开销小，可能显著节省数据库 CPU 使用
      get "private-messages-all/:username" => "list#private_messages", as: "topics_private_messages_override", defaults: { format: :json }
      get "private-messages-all-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent_override", defaults: { format: :json }
      get "private-messages-all-new/:username" => "list#private_messages_new", as: "topics_private_messages_new_override", defaults: { format: :json }
      get "private-messages-all-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread_override", defaults: { format: :json }
      get "private-messages-all-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive_override", defaults: { format: :json }
    end
  end
end

```

部署上述猴子补丁后，我们论坛数据库的 CPU 使用率如下：

 ![image](https://global.discourse-cdn.com/meta/original/3X/5/3/5396b5d299e3953cf492b5e590cd0daa1259e680.png)

@tgxworld 你需要再次检查 `*/private-messages-all/*` 路由的具体实现，显然其中存在问题，对于大型论坛数据库来说效率太低。要么是未使用正确的数据库索引，要么是查询生成导致了极其昂贵的查询（尤其在 PSQL 10 上，PSQL 12/13 尚不确定）。

当前的实现几乎让论坛瘫痪，CPU 使用率从约 15% 飙升至持续的 100%，并导致所有其他论坛功能性能变慢。我不明白为什么“个人/群组收件箱”查询耗时不到 50 毫秒，而“所有收件箱”查询却需要 20 多分钟才能完成。

你可以使用 @forkythetoy 刚才发布的 analyze 转储文件，查看之前 20 分钟以上的运行记录。

---

<div class="post-metadata">

### Author: ![Hooksmith](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hooksmith/32/142826_2.png) [@Hooksmith](https://meta.discourse.org/u/Hooksmith)
#### Post date: [2021年九月9日 11:39 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/30 "2021-09-09T11:39:43Z")

</div>

@Falco 我刚刚注意到您将我们的话题合并到这里了，但这似乎涉及的是另一个端点。此错误报告针对的是 `private-message-topic-tracking-state` 端点，而我们讨论的是 `*/private-messages-all/*`。这可能会导致此处的一些混淆，对此我表示歉意。（我最初链接的是这个，可能引发了混淆）

在我们的论坛上，`private-message-topic-tracking-state` 响应很快，所以这对我们来说不是问题。

---

<div class="post-metadata">

### Author: ![blattersturm](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/blattersturm/32/76134_2.png) [@blattersturm](https://meta.discourse.org/u/blattersturm)
#### Post date: [2021年九月9日 13:50 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/31 "2021-09-09T13:50:38Z")

</div>

> [@Hooksmith](#):
>
> `*/private-messages-all/*`。

对我们来说，这条查询的数据库耗时约为 200-300 毫秒。虽然比预期稍长，但仍在正常范围内，没错。

不过，我们使用的是 Postgres 13。

---

<div class="post-metadata">

### Author: ![tgxworld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tgxworld/32/106117_2.png) [@tgxworld](https://meta.discourse.org/u/tgxworld)
#### Post date: [2021年九月10日 06:09 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/32 "2021-09-10T06:09:42Z")

</div>

@Hooksmith 我已经有一个修复方案在推进中

> <https://github.com/discourse/discourse/pull/14304>
>
> First reported in https://meta.discourse.org/t/-/202482/19
> 
> There are two opti…mizations being applied here:
> 
> 1. Fetch a user's group ids in a seperate query instead of including it
> as a sub-query. When I tried a subquery, the query plan becomes very
> inefficient.
> 
> 1. Join against the \`topic\_allowed\_users\` and \`topic\_allowed\_groups\`
> table instead of doing an IN against a subquery where we UNION the
> \`topic\_id\`s from the two tables. From my profiling, this enables PG to
> do a backwards index scan on the \`index\_topics\_on\_timestamps\_private\`
> index.
> 
> This commit fixes a bug where listing all messages was incorrectly
> excluding topics if a topic has been archived by a group even if the
> user did not belong to the group.
> 
> This commit also fixes another bug where dismissing private messages
> selectively was subjected to the default limit of 30.

---

<div class="post-metadata">

### Author: ![tgxworld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tgxworld/32/106117_2.png) [@tgxworld](https://meta.discourse.org/u/tgxworld)
#### Post date: [2021年九月15日 06:54 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/33 "2021-09-15T06:54:44Z")

</div>

> [@forkythetoy](#):
>
> 另外请注意，我们目前使用的是 PG 10.17，因为我们的输出结果似乎存在较大差异。

> [@Hooksmith](#):
>
> 要么实现时未使用正确的数据库索引，要么查询生成导致了极其昂贵的查询（特别是在 PSQL 10 上，对 12/13 版本我不太确定）。

@Hooksmith @forkythetoy 你们能否升级到 PG 13？这是目前 Discourse 要求的最低版本。此外，当查询未使用相同的 PG 版本执行时，我也更难比较查询计划。

> [@tgxworld](#):
>
> 我已经在修复流程中。

我不得不回退此更改，因为新查询的性能在不同用户之间存在过大差异。

---

<div class="post-metadata">

### Author: ![tgxworld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tgxworld/32/106117_2.png) [@tgxworld](https://meta.discourse.org/u/tgxworld)
#### Post date: [2021年九月16日 08:08 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/34 "2021-09-16T08:08:42Z")

</div>

@blattersturm 你仍然发现主题追踪状态的性能很慢吗？

---

<div class="post-metadata">

### Author: ![blattersturm](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/blattersturm/32/76134_2.png) [@blattersturm](https://meta.discourse.org/u/blattersturm)
#### Post date: [2021年九月16日 08:41 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/35 "2021-09-16T08:41:55Z")

</div>

不确定，已经好几天没有进行升级了。有没有什么提交可以合并看看是否有改进？

---

<div class="post-metadata">

### Author: ![tgxworld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tgxworld/32/106117_2.png) [@tgxworld](https://meta.discourse.org/u/tgxworld)
#### Post date: [2021年九月16日 09:49 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/36 "2021-09-16T09:49:17Z")

</div>

没有，什么都没变。但如果你能提供该查询的 EXPLAIN ANALYZE 结果，那会很有帮助。

---

<div class="post-metadata">

### Author: ![tgxworld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tgxworld/32/106117_2.png) [@tgxworld](https://meta.discourse.org/u/tgxworld)
#### Post date: [2021年十月4日 01:39 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/37 "2021-10-04T01:39:50Z")

</div>

> [@Hooksmith](#):
>
> 我们通过将所有 `*/private-messages-all/*` 路由临时重定向到 `*/private-messages/*` 来修复了这个问题。

请注意，由于性能方面的考虑，我们暂时恢复了所有收件箱。

> <https://github.com/discourse/discourse/commit/9d5da2b383765becb824a8f3ff3665abc8e527fa>
>
> The all inboxes was introduced in
> 016efeadf6f242e04daf5ef8e18c2ca708a1392d but …we decided to roll it back
> for performance reasons. The main performance challenge here is that PG
> has to basically loop through all the PMs that a user is allowed to view
> before being able to order by \`Topic#bumped\_at\`. The all inboxes was not
> planned as part of the new/unread filter so we've decided not to tackle
> the performance issue for the upcoming release.
> 
> Follow-up to 016efeadf6f242e04daf5ef8e18c2ca708a1392d

---

<div class="post-metadata">

### Author: ![tgxworld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tgxworld/32/106117_2.png) [@tgxworld](https://meta.discourse.org/u/tgxworld)
#### Post date: [2021年十月18日 08:00 UTC](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482/38 "2021-10-18T08:00:11Z")

</div>

此主题在 14 天后自动关闭。不再允许新回复。

[上一頁](https://meta.discourse.org/t/slow-loading-on-private-message-topic-tracking-state-json/202482.md?page=1)
