データベースの低速により、ユーザーサマリーページの読み込みに時間がかかる

こんにちは、

ユーザーのサマリーページにアクセスする際の読み込み時間が非常に長いという問題に直面しています。ユーザーが当サイトでより活発に活動するほど、サマリーの読み込みに時間がかかるようです。これは確かに当然のことですが、当サイトでの読み込み時間の差は甚大です。
数週間程度の活動しかない「新規」ユーザーのサマリーページの読み込みには約 1 秒しかかかりませんが、数年にわたり毎日活動しているユーザーのページを読み込むには 30〜40 秒もかかってしまいます。

そこでデータベースを確認したところ、topic_views テーブルのサイズ(インデックスを含む)が 62 GB と非常に大きいことに驚きました。

以下が当サイトの 7 つの最大のテーブルです:

relation total_size table_size index_size reltuples
topic_views 62 GB 17 GB 45 GB 399215000
posts 27 GB 22 GB 5022 MB 9123860
top_topics 15 GB 708 MB 15 GB 1602180
post_search_data 15 GB 12 GB 2849 MB 8181010
incoming_links 12 GB 5330 MB 6647 MB 90008900
user_actions 3184 MB 877 MB 2307 MB 11872800
topics 2117 MB 1035 MB 1082 MB 1613070

これをテストするため、サマリーの読み込みに非常に時間がかかることが分かっているユーザーの ID を選び、topic_views テーブルでその ID を用いてカウントを実行しました。このクエリの実行時間は、ユーザーサマリーの読み込み時間とほぼ同じでした。つまり、遅延の原因は「閲覧したトピック」の部分が担っていることが分かりました。

以前のトピックで説明した通り、旧バージョン(v1.2.4 + 修正版)の Discourse ベースのサイトを v2.4.0-beta.2 にアップグレードし、現在は Discourse v2.4.0-beta6 を稼働させています。そのため、何らかのデータが残留している可能性があります。しかし、何を削除すればよいかは分かりません。

この時点で、次に何をすべきか、あるいは何を調整すべきか非常に不安です。当社のインストール環境は完全に Azure 上で稼働しており、Azure Database for PostgreSQL の外部インスタンスを使用しています。また、postgres.10.template.yml に記載されている設定を適用しています。topic_views テーブルのサイズ(特にインデックス)が他のテーブルと比較して「大きすぎる」のか、それとも非常に正常な範囲なのかさえ分かりません。

どのようなヒント、考察、あるいはアイデアでも歓迎いたします。

よろしくお願いいたします。
Sascha Hofmann

追伸:
付け加えるのを忘れていましたが、この問題により /u/<username>/summary.json の読み込み時に複数の 502 エラーが発生しています(エラーはサイト自体に表示され、nginx のエラーページやアプリケーションゲートウェイによるものではありません)。

管理者/スタッフとして、あるいは匿名として表示していますか?スタッフ表示ははるかに高額です。

管理者/スタッフとして /u/<username>/summary を表示しても、通常のユーザーアカウントとして表示しても、結果に違いはありません。また、「ユーザープロフィールを公開から非表示にする」設定も有効になっているため、匿名ユーザーにはプロフィールが表示されません(テスト用に無効化しましたが、結果に違いはありません。なぜなら「閲覧したトピック」もサマリーに含まれているためです)。

同じデータベースを繰り返し移行、変更、または再構築していませんか?データベースの統計情報を更新するために、VACUUM が必要かもしれません。Discourse インストールで通常見られる範囲を大きく超える 30 秒のクエリが発生しています(ただし、あなたのデータベースは確かに大規模です)。

VACUUM FULL は、いくつかのダウンタイムを受け入れられるのであれば、試す価値があります。

また、データベースは高速な SSD ストレージと大量の RAM を搭載していますか?それは極めて重要です。

問題を正確に把握するために:

  1. app.yml ファイルを編集し、DISCOURSE_DEVELOPER_EMAILS に管理者ユーザーのメールアドレスを追加します。

  2. リビルドを実行します。

  3. ステップ 1 で設定したユーザーとしてログインし、読み込みが遅いページを開きます。

  4. mini-profiler の結果を共有します。

この内容と展開されたウィンドウの情報を共有してください:

何度かテストを行いましたが、いつも古いデータセットの完全なコピーを使用していました。数週間かけて前の所有者による変更が正常に元通りになったことを確認した後、アップグレードと移行を一度だけ実行しました。

確かに試す価値はありますが、どれくらい時間がかかるか確信が持てません。とはいえ、フル VACUUM を検討すべきでしょう。特に、以前のデータベースで既にいくつかの問題が発生していたためです already

はい。すべてのデータはサーバーの SSD に保存されており、40GB の RAM がバックアップとして機能しています(全体として約 60% が使用されており、負荷が高くなっても 100% に達してプラトーになることはありません)。

アドバイスありがとうございます、試してみます。
私たちは独自の Docker イメージを使用しており、app.yml が存在しないため、discourse.conf の developer_emails にメールアドレスを追加することで、同じ動作を実現する必要があります。

Rails コンソールに入り、Developers.create!(user_id: 123)を実行してください。123 はあなたのユーザー ID です。

残念ながら動作していません(はい、123 は既に置き換えました :slight_smile:) :

discourse@2d5c3bf04550:~$ rails console --environment=production
Loading production environment (Rails 6.0.0)
irb(main):001:0> Developers.create!(user_id: 123)
Traceback (most recent call last):
        1: from (irb):1
NameError (uninitialized constant Developers)

別のアプローチ:

discourse@2d5c3bf04550:~$ rails runner --environment=production make_me_dev.rb
Traceback (most recent call last):
/var/www/discourse/bin/rails: Bootsnap::LoadPathCache::FallbackScan
	19: from /var/www/discourse/bin/rails:17:in `<main>'
	18: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `require'
	17: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:291:in `load_dependency'
	16: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:325:in `block in require'
	15: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
	14: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
	13: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
	12: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
	11: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
	10: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.0/lib/rails/commands.rb:18:in `<main>'
	 9: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.0/lib/rails/command.rb:46:in `invoke'
	 8: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.0/lib/rails/command/base.rb:65:in `perform'
	 7: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/thor-0.20.3/lib/thor.rb:387:in `dispatch'
	 6: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/thor-0.20.3/lib/thor/invocation.rb:126:in `invoke_command'
	 5: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/thor-0.20.3/lib/thor/command.rb:27:in `run'
	 4: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.0/lib/rails/commands/runner/runner_command.rb:42:in `perform'
	 3: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:52:in `load'
	 2: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:69:in `rescue in load'
	 1: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:69:in `load'
make_me_dev.rb:1:in `<main>': uninitialized constant Developers (NameError)
discourse@2d5c3bf04550:~$ cat make_me_dev.rb
Developers.create!(user_id: 123)

discourse.conf の方法で試して、できるだけ早く要求されたデータを提供します。

これまでのアドバイスに感謝します!

だからこそ、私たちは常に人々に Discourse の公式サポートされているインストール方法を使用するよう伝えているのです。そうすれば、サポートが必要な際に標準的なツールを使って対応できるからです。

はい、おそらくはすべてのプロセスを起動するために supervisord を使用しているためでしょう。

ともあれ、ご要望の出力はこちらです(HTML コンテンツを ZIP 化):
_u_x_strom_summary.json-13498.2ms-ProfilingResults.zip (94.5 KB)

このリクエストには 13 秒かかりましたが、サイトは 2 回読み込む必要がありました。最初の試みは長すぎたため、502 エラーが発生しました。そのため、すでに何かがキャッシュされていたのかもしれません。

51 件の SQL クエリを実行するのに 13 秒以上かかりました。データベースの設定が誤っているか、性能不足の可能性があります。

主な原因
SELECT "posts"."id" AS t0_r0, "posts"."user_id" AS t0_r1, "posts"."topic_id" AS t0_r2, "posts"."post_number" AS t0_r3, "posts"."raw" AS t0_r4, "posts"."cooked" AS t0_r5, "posts"."created_at" AS t0_r6, "posts"."updated_at" AS t0_r7, "posts"."reply_to_post_number" AS t0_r8, "posts"."reply_count" AS t0_r9, "posts"."quote_count" AS t0_r10, "posts"."deleted_at" AS t0_r11, "posts"."off_topic_count" AS t0_r12, "posts"."like_count" AS t0_r13, "posts"."incoming_link_count" AS t0_r14, "posts"."bookmark_count" AS t0_r15, "posts"."avg_time" AS t0_r16, "posts"."score" AS t0_r17, "posts"."reads" AS t0_r18, "posts"."post_type" AS t0_r19, "posts"."sort_order" AS t0_r20, "posts"."last_editor_id" AS t0_r21, "posts"."hidden" AS t0_r22, "posts"."hidden_reason_id" AS t0_r23, "posts"."notify_moderators_count" AS t0_r24, "posts"."spam_count" AS t0_r25, "posts"."illegal_count" AS t0_r26, "posts"."inappropriate_count" AS t0_r27, "posts"."last_version_at" AS t0_r28, "posts"."user_deleted" AS t0_r29, "posts"."reply_to_user_id" AS t0_r30, "posts"."percent_rank" AS t0_r31, "posts"."notify_user_count" AS t0_r32, "posts"."like_score" AS t0_r33, "posts"."deleted_by_id" AS t0_r34, "posts"."edit_reason" AS t0_r35, "posts"."word_count" AS t0_r36, "posts"."version" AS t0_r37, "posts"."cook_method" AS t0_r38, "posts"."wiki" AS t0_r39, "posts"."baked_at" AS t0_r40, "posts"."baked_version" AS t0_r41, "posts"."hidden_at" AS t0_r42, "posts"."self_edits" AS t0_r43, "posts"."reply_quoted" AS t0_r44, "posts"."via_email" AS t0_r45, "posts"."raw_email" AS t0_r46, "posts"."public_version" AS t0_r47, "posts"."action_code" AS t0_r48, "posts"."image_url" AS t0_r49, "posts"."locked_by_id" AS t0_r50, "topics"."id" AS t1_r0, "topics"."title" AS t1_r1, "topics"."last_posted_at" AS t1_r2, "topics"."created_at" AS t1_r3, "topics"."updated_at" AS t1_r4, "topics"."views" AS t1_r5, "topics"."posts_count" AS t1_r6, "topics"."user_id" AS t1_r7, "topics"."last_post_user_id" AS t1_r8, "topics"."reply_count" AS t1_r9, "topics"."featured_user1_id" AS t1_r10, "topics"."featured_user2_id" AS t1_r11, "topics"."featured_user3_id" AS t1_r12, "topics"."avg_time" AS t1_r13, "topics"."deleted_at" AS t1_r14, "topics"."highest_post_number" AS t1_r15, "topics"."image_url" AS t1_r16, "topics"."like_count" AS t1_r17, "topics"."incoming_link_count" AS t1_r18, "topics"."category_id" AS t1_r19, "topics"."visible" AS t1_r20, "topics"."moderator_posts_count" AS t1_r21, "topics"."closed" AS t1_r22, "topics"."archived" AS t1_r23, "topics"."bumped_at" AS t1_r24, "topics"."has_summary" AS t1_r25, "topics"."archetype" AS t1_r26, "topics"."featured_user4_id" AS t1_r27, "topics"."notify_moderators_count" AS t1_r28, "topics"."spam_count" AS t1_r29, "topics"."pinned_at" AS t1_r30, "topics"."score" AS t1_r31, "topics"."percent_rank" AS t1_r32, "topics"."subtype" AS t1_r33, "topics"."slug" AS t1_r34, "topics"."deleted_by_id" AS t1_r35, "topics"."participant_count" AS t1_r36, "topics"."word_count" AS t1_r37, "topics"."excerpt" AS t1_r38, "topics"."pinned_globally" AS t1_r39, "topics"."pinned_until" AS t1_r40, "topics"."fancy_title" AS t1_r41, "topics"."highest_staff_post_number" AS t1_r42, "topics"."featured_link" AS t1_r43, "topics"."reviewable_score" AS t1_r44 FROM "posts" INNER JOIN "topics" ON ("topics"."deleted_at" IS NULL) AND "topics"."id" = "posts"."topic_id" WHERE ("posts"."deleted_at" IS NULL) AND (posts.post_type IN (1,2,3,4)) AND ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') AND "topics"."visible" = TRUE AND (topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE NOT read_restricted OR id IN (1,3,6,100,141,202,229,233,235,248,262,594,595,609))) AND "posts"."user_id" = 643476 AND (post_number > 1) ORDER BY posts.like_count DESC, posts.created_at DESC LIMIT 6; 

6248.3 ms 要

SELECT "topic_links"."id" AS t0_r0, "topic_links"."topic_id" AS t0_r1, "topic_links"."post_id" AS t0_r2, "topic_links"."user_id" AS t0_r3, "topic_links"."url" AS t0_r4, "topic_links"."domain" AS t0_r5, "topic_links"."internal" AS t0_r6, "topic_links"."link_topic_id" AS t0_r7, "topic_links"."created_at" AS t0_r8, "topic_links"."updated_at" AS t0_r9, "topic_links"."reflection" AS t0_r10, "topic_links"."clicks" AS t0_r11, "topic_links"."link_post_id" AS t0_r12, "topic_links"."title" AS t0_r13, "topic_links"."crawled_at" AS t0_r14, "topic_links"."quote" AS t0_r15, "topic_links"."extension" AS t0_r16, "topics"."id" AS t1_r0, "topics"."title" AS t1_r1, "topics"."last_posted_at" AS t1_r2, "topics"."created_at" AS t1_r3, "topics"."updated_at" AS t1_r4, "topics"."views" AS t1_r5, "topics"."posts_count" AS t1_r6, "topics"."user_id" AS t1_r7, "topics"."last_post_user_id" AS t1_r8, "topics"."reply_count" AS t1_r9, "topics"."featured_user1_id" AS t1_r10, "topics"."featured_user2_id" AS t1_r11, "topics"."featured_user3_id" AS t1_r12, "topics"."avg_time" AS t1_r13, "topics"."deleted_at" AS t1_r14, "topics"."highest_post_number" AS t1_r15, "topics"."image_url" AS t1_r16, "topics"."like_count" AS t1_r17, "topics"."incoming_link_count" AS t1_r18, "topics"."category_id" AS t1_r19, "topics"."visible" AS t1_r20, "topics"."moderator_posts_count" AS t1_r21, "topics"."closed" AS t1_r22, "topics"."archived" AS t1_r23, "topics"."bumped_at" AS t1_r24, "topics"."has_summary" AS t1_r25, "topics"."archetype" AS t1_r26, "topics"."featured_user4_id" AS t1_r27, "topics"."notify_moderators_count" AS t1_r28, "topics"."spam_count" AS t1_r29, "topics"."pinned_at" AS t1_r30, "topics"."score" AS t1_r31, "topics"."percent_rank" AS t1_r32, "topics"."subtype" AS t1_r33, "topics"."slug" AS t1_r34, "topics"."deleted_by_id" AS t1_r35, "topics"."participant_count" AS t1_r36, "topics"."word_count" AS t1_r37, "topics"."excerpt" AS t1_r38, "topics"."pinned_globally" AS t1_r39, "topics"."pinned_until" AS t1_r40, "topics"."fancy_title" AS t1_r41, "topics"."highest_staff_post_number" AS t1_r42, "topics"."featured_link" AS t1_r43, "topics"."reviewable_score" AS t1_r44, "posts"."id" AS t2_r0, "posts"."user_id" AS t2_r1, "posts"."topic_id" AS t2_r2, "posts"."post_number" AS t2_r3, "posts"."raw" AS t2_r4, "posts"."cooked" AS t2_r5, "posts"."created_at" AS t2_r6, "posts"."updated_at" AS t2_r7, "posts"."reply_to_post_number" AS t2_r8, "posts"."reply_count" AS t2_r9, "posts"."quote_count" AS t2_r10, "posts"."deleted_at" AS t2_r11, "posts"."off_topic_count" AS t2_r12, "posts"."like_count" AS t2_r13, "posts"."incoming_link_count" AS t2_r14, "posts"."bookmark_count" AS t2_r15, "posts"."avg_time" AS t2_r16, "posts"."score" AS t2_r17, "posts"."reads" AS t2_r18, "posts"."post_type" AS t2_r19, "posts"."sort_order" AS t2_r20, "posts"."last_editor_id" AS t2_r21, "posts"."hidden" AS t2_r22, "posts"."hidden_reason_id" AS t2_r23, "posts"."notify_moderators_count" AS t2_r24, "posts"."spam_count" AS t2_r25, "posts"."illegal_count" AS t2_r26, "posts"."inappropriate_count" AS t2_r27, "posts"."last_version_at" AS t2_r28, "posts"."user_deleted" AS t2_r29, "posts"."reply_to_user_id" AS t2_r30, "posts"."percent_rank" AS t2_r31, "posts"."notify_user_count" AS t2_r32, "posts"."like_score" AS t2_r33, "posts"."deleted_by_id" AS t2_r34, "posts"."edit_reason" AS t2_r35, "posts"."word_count" AS t2_r36, "posts"."version" AS t2_r37, "posts"."cook_method" AS t2_r38, "posts"."wiki" AS t2_r39, "posts"."baked_at" AS t2_r40, "posts"."baked_version" AS t2_r41, "posts"."hidden_at" AS t2_r42, "posts"."self_edits" AS t2_r43, "posts"."reply_quoted" AS t2_r44, "posts"."via_email" AS t2_r45, "posts"."raw_email" AS t2_r46, "posts"."public_version" AS t2_r47, "posts"."action_code" AS t2_r48, "posts"."image_url" AS t2_r49, "posts"."locked_by_id" AS t2_r50 FROM "topic_links" INNER JOIN "topics" ON ("topics"."deleted_at" IS NULL) AND "topics"."id" = "topic_links"."topic_id" INNER JOIN "posts" ON ("posts"."deleted_at" IS NULL) AND "posts"."id" = "topic_links"."post_id" WHERE (posts.post_type IN (1,2,3,4)) AND ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') AND "topics"."visible" = TRUE AND (topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE NOT read_restricted OR id IN (1,3,6,100,141,202,229,233,235,248,262,594,595,609))) AND "topic_links"."user_id" = 643476 AND "topic_links"."internal" = FALSE AND "topic_links"."reflection" = FALSE AND "topic_links"."quote" = FALSE ORDER BY clicks DESC, topic_links.created_at DESC LIMIT 6; 

258.3 ms 要

SELECT acting_user_id, COUNT(*) FROM "user_actions" INNER JOIN "topics" ON ("topics"."deleted_at" IS NULL) AND "topics"."id" = "user_actions"."target_topic_id" INNER JOIN "posts" ON ("posts"."deleted_at" IS NULL) AND "posts"."id" = "user_actions"."target_post_id" WHERE ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') AND "topics"."visible" = TRUE AND (topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE NOT read_restricted OR id IN (1,3,6,100,141,202,229,233,235,248,262,594,595,609))) AND "user_actions"."user_id" = 643476 AND "user_actions"."action_type" = 2 GROUP BY "user_actions"."acting_user_id" ORDER BY COUNT(*) DESC LIMIT 6; 

245.5 ms 要

SELECT user_actions.user_id, COUNT(*) FROM "user_actions" INNER JOIN "topics" ON ("topics"."deleted_at" IS NULL) AND "topics"."id" = "user_actions"."target_topic_id" INNER JOIN "posts" ON ("posts"."deleted_at" IS NULL) AND "posts"."id" = "user_actions"."target_post_id" WHERE ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') AND "topics"."visible" = TRUE AND (topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE NOT read_restricted OR id IN (1,3,6,100,141,202,229,233,235,248,262,594,595,609))) AND "user_actions"."action_type" = 2 AND "user_actions"."acting_user_id" = 643476 GROUP BY "user_actions"."user_id" ORDER BY COUNT(*) DESC LIMIT 6; 

277.2 ms 要

SELECT replies.user_id, COUNT(*) FROM "posts" INNER JOIN "topics" ON ("topics"."deleted_at" IS NULL) AND "topics"."id" = "posts"."topic_id" JOIN posts replies ON posts.topic_id = replies.topic_id AND posts.reply_to_post_number = replies.post_number WHERE ("posts"."deleted_at" IS NULL) AND (posts.post_type IN (1,2,3,4)) AND ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') AND "topics"."visible" = TRUE AND (topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE NOT read_restricted OR id IN (1,3,6,100,141,202,229,233,235,248,262,594,595,609))) AND "posts"."user_id" = 643476 AND (replies.user_id <> 643476) GROUP BY replies.user_id ORDER BY COUNT(*) DESC LIMIT 6; 

3064.6 ms 要

SELECT category_id FROM "posts" INNER JOIN "topics" ON ("topics"."deleted_at" IS NULL) AND "topics"."id" = "posts"."topic_id" WHERE ("posts"."deleted_at" IS NULL) AND (posts.post_type IN (1,2,3,4)) AND ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') AND "topics"."visible" = TRUE AND (topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE NOT read_restricted OR id IN (1,3,6,100,141,202,229,233,235,248,262,594,595,609))) AND "posts"."user_id" = 643476 GROUP BY topics.category_id ORDER BY COUNT(*) DESC LIMIT 6; 

2283.3 ms 要

SELECT category_id, COUNT(*) FROM "posts" INNER JOIN "topics" ON ("topics"."deleted_at" IS NULL) AND "topics"."id" = "posts"."topic_id" WHERE ("posts"."deleted_at" IS NULL) AND (posts.post_type IN (1,2,3,4)) AND ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') AND "topics"."visible" = TRUE AND (topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE NOT read_restricted OR id IN (1,3,6,100,141,202,229,233,235,248,262,594,595,609))) AND "posts"."user_id" = 643476 AND (post_number > 1) AND (topics.category_id in (64,13,59,124,327,122)) GROUP BY topics.category_id ORDER BY COUNT(*) DESC; 

811.5 ms 要

Azure にはホストされたサービス向けのデータベース統計情報が何らかの形で提供されているはずです。それらを確認し、変更の必要性を評価してください。

また、インストール内の /sidekiq URL を確認して、データベースを繁忙にさせているキュー競合がないかチェックしてください。

それは最初に確認しました。当社のインスタンスの状況は以下の通りです。

  • 8 コア(利用率約 16.18%、一時的に 60% に上昇)
  • 40GB RAM(使用率約 60%、急増なし)
  • 利用可能な IOPS 2244(利用率約 2.5%、一時的に 24% に上昇)

前述の通り、当社は貴社の postgres.10.template.yml で説明されている構成を使用しています。それ以外の設定はすべてデフォルトのままです。改めて確認する必要があるようです。

現在、Sidekiq は正常に動作しています。ビジー 0、キューイング 0、リトライ 0、スケジュール済み 1、デッド 0です。ジョブリストは現在空です。

まず結論から申し上げますと、適用できる調整があるため、最初に PostgreSQL の設定を確認します。それでも解決しない場合は、PostgreSQL インスタンスのアップグレードや完全な VACUUM 実行を検討する必要があります。

これまでのご対応に感謝し、良い週末をお過ごしください。
敬具
サシャ

マシンに 40GB の RAM が搭載されている場合、postgres.10.template.yml のデフォルト設定はもはや適切ではありません。これは samples/standalone.yml が示している通りです:

こんにちは、

ご返信ありがとうございます。Azure 上の PostgreSQL インスタンスを使用する際にはいくつかの制限があります。effective_cache_sizemax_connectionsmaintenance_worker_memshared_buffers などの設定値を指定することができません。
このサポートリクエストを作成した時点では、「General Purpose」ティアを使用しており、40GB の RAM が割り当てられていましたが、shared_buffers は 1GB、effective_cache_size は 2.5GB しか確保されていませんでした。
昨日から「Memory Optimized」ティアに切り替えたところ、RAM が 80GB に倍増し、shared_buffers は 2GB、effective_cache_size は 5GB になりました。
調整可能な設定である work_mem は、ログに temporary file エントリがないため、現在 128MB に設定されています。

興味深いことに、ティアを切り替えた直後、vCore やストレージを増やすことなく、CPU 利用率と IOPS 利用率が低下しました。これは、キャッシュとバッファが小さすぎることが原因で問題が発生していたことが明確です。

それでも、一部のユーザー(特にスタッフユーザーや長期利用ユーザー)のサマリーページや about ページの読み込み時間は依然として長いですが、以前と比較すると大幅に改善され(約 50% に短縮)、以前よりはるかに良くなっています。

よろしくお願いいたします。

追伸:
同様の問題に直面しており、PostgreSQL インストールに対してより多くの制御権限をお持ちの方には、以下の小冊子が役立つかもしれません:

聞いてよかったです。次のステップとしては、コスト最適化のために 4vCPU メモリ最適化インスタンスで済むかどうかを確認するか、あるいは自分で運用するように切り替えることを検討してください。

ああ、私たちは 8 vCore を運用しており、それにより 80GB の RAM となっています。shared_buffers は現在 2GB ですが、このティアと vCore 数に対しては 16GB に設定すべきでした。ただし、Azure サポートチームと連絡を取り、修正を依頼しています。

追伸
実はすでに shared_buffers は 16GB に設定されています。SELECT * FROM pg_settings WHERE name = 'shared_buffers'; の出力を誤って解釈していました。単位は 8KB です。

そのため、このトピックはクローズできると思います。皆様の努力に感謝し、Azure サポートチームと協力して、今後数日間でより良いパフォーマンスを達成できることを願っています。

再追伸
@riking さん、すみません。誤解していました。4 vCore に減らすのではなく、8 vCore のまま運用するのが良いと思います。目指すパフォーマンスが達成でき次第、早速試してみたいと思います。