Lange Ladezeiten für die Benutzerübersichtsseite bei langsamer Datenbank

Hallo,

wir haben massive Ladezeiten beim Aufruf einer Benutzer-Zusammenfassungsseite. Es scheint, dass die Zusammenfassung umso länger lädt, je aktiver ein Nutzer auf unserer Seite interagiert. Das mag zwar offensichtlich klingen, doch der Unterschied in den Ladezeiten auf unserer Seite ist enorm.

Das Laden der Zusammenfassungsseite eines „neuen" Benutzers (einige Wochen Aktivität) dauert ca. 1 Sekunde, während das Laden einer Seite eines Benutzers mit täglicher Aktivität über Jahre hinweg bis zu 30–40 Sekunden in Anspruch nimmt.

Wir haben daher die Datenbank überprüft und waren über die Größe der Tabelle topic_views (einschließlich Indizes) von 62 GB ziemlich beeindruckt.

Hier sind unsere sieben größten Tabellen:

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

Zum Testen haben wir die ID eines Benutzers ausgewählt, bei dem wir wissen, dass die Zusammenfassung sehr lange lädt, und eine COUNT-Abfrage mit dieser ID auf der Tabelle topic_views ausgeführt. Diese Abfrage dauerte fast genauso lange wie das Laden der Benutzerzusammenfassung. Der Teil „topics viewed" ist also für diese Verzögerung verantwortlich.

Wie in früheren Themen erklärt, haben wir eine alte Discourse-basierte Seite (v1.2.4 + Modifikationen) auf v2.4.0-beta.2 aktualisiert und laufen nun mit Discourse v2.4.0-beta6. Möglicherweise sind daher noch einige Daten übrig geblieben. Wir wissen jedoch nicht, was gelöscht werden kann.

An diesem Punkt sind wir uns ziemlich unsicher, was als Nächstes zu tun oder zu optimieren ist. Unsere Installation läuft vollständig auf Azure unter Verwendung einer externen Instanz von Azure Database for PostgreSQL, und wir haben die in Ihrer postgres.10.template.yml beschriebene Konfiguration angewendet. Wir wissen nicht einmal, ob die Größe der Tabelle topic_views (insbesondere des Index) im Verhältnis zu den anderen Tabellen „zu groß" ist oder ob dies völlig normal ist.

Jeder Hinweis, Gedanke oder jede Idee wird geschätzt.

Mit freundlichen Grüßen
Sascha Hofmann

P.S.
Ich habe vergessen zu erwähnen, dass wir aufgrund dessen mehrere 502-Fehler haben (direkt auf der Seite angezeigt, also keine nginx-Fehlerseite oder Application Gateway), wenn /u/<username>/summary.json geladen wird.

Sehst du es als Admin/Mitarbeiter oder als Anonymer? Die Ansicht für Mitarbeiter ist weitaus teurer.

Es macht keinen Unterschied, ob ich /u/<username>/summary als Admin/Mitarbeiter oder mit meinem normalen Benutzerkonto ansehe. Wir haben zudem die Option „Benutzerprofile vor der Öffentlichkeit verbergen

Haben Sie dieselbe Datenbank wiederholt migriert, geändert oder neu aufgebaut? Möglicherweise benötigt Ihre Datenbank eine Vakuumsicherung, um die Statistiken zu aktualisieren. Abfragen von 30 Sekunden liegen weit außerhalb des normalen Bereichs, den wir bei Discourse-Installationen beobachten (obwohl Ihre Datenbank admittedly groß ist).

VACUUM FULL ist einen Versuch wert, wenn Sie einige Ausfallzeiten in Kauf nehmen können.

Ist deine Datenbank auch auf schnellem SSD-Speicher mit viel RAM? Das ist entscheidend.

Um genau zu wissen, was das Problem ist:

  1. Bearbeiten Sie die Datei app.yml und fügen Sie Ihre Administrator-E-Mail-Adresse zu DISCOURSE_DEVELOPER_EMAILS hinzu.

  2. Erstellen Sie neu.

  3. Laden Sie die langsame Seite, während Sie als der in Schritt 1 festgelegte Benutzer angemeldet sind.

  4. Teilen Sie das Ergebnis des Mini-Profilers.

Teilen Sie den Inhalt davon und des erweiterten Fensters:

Wir haben es mehrmals getestet, aber immer mit einer frischen Kopie des alten Datensatzes. Nach ein paar Wochen, sobald wir sicher waren, dass wir die Änderungen des vorherigen Eigentümers erfolgreich rückgängig gemacht hatten, haben wir das Upgrade und die Migration einmal durchgeführt.

Das ist definitiv einen Versuch wert, aber ich bin mir nicht ganz sicher, wie lange das dauern wird. Aber ja, wir sollten ein vollständiges Vacuum in Betracht ziehen. Besonders da wir bereits Probleme mit der älteren Datenbank hatten bereits.

Ja. Alle Daten werden auf einer Server-SSD gespeichert und durch 40 GB RAM unterstützt (wovon insgesamt etwa 60 % genutzt werden, ohne dass es bei höherer Last zu Plateaus bei 100 % kommt).

Danke für diesen Rat, ich werde es ausprobieren. Da wir unser eigenes Docker-Image verwenden, in dem die app.yml fehlt, sollten wir das gleiche Verhalten erreichen, indem wir die E-Mail-Adresse(n) zu developer_emails in der discourse.conf hinzufügen.

Du kannst in die Rails-Konsole gehen und Developers.create!(user_id: 123) verwenden, wobei 123 deine Benutzer-ID ist.

Leider funktioniert es nicht (ja, ich habe 123 bereits ersetzt :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)

Ein weiterer Ansatz:

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)

Ich werde es mit dem discourse.conf-Ansatz versuchen und die angeforderten Daten so schnell wie möglich bereitstellen.

Vielen Dank bisher für deinen Rat!

Genau deshalb empfehlen wir den Leuten immer, die offiziell unterstützte Methode zur Installation von Discourse zu verwenden. So können wir bei Bedarf mit Standard-Tools helfen.

Ja, vielleicht liegt es daran, dass wir supervisord verwenden, um alle Prozesse zu starten.

Wie auch immer, hier ist die angeforderte Ausgabe (z. HTML-Inhalt):
_u_x_strom_summary.json-13498.2ms-ProfilingResults.zip (94,5 KB)

Diese Anfrage dauerte 13 Sekunden, aber ich musste die Seite zweimal laden. Wieder dauerte der erste Versuch zu lange, was zu einem 502-Fehler führte. Vielleicht waren also einige Dinge bereits zwischengespeichert.

Für die Ausführung von 51 SQL-Abfragen wurden mehr als 13 Sekunden benötigt. Ihre Datenbank ist entweder schwerwiegend falsch konfiguriert oder unterdimensioniert.

Hauptverursacher
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; 

Dauer: 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; 

Dauer: 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; 

Dauer: 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; 

Dauer: 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; 

Dauer: 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; 

Dauer: 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; 

Dauer: 811,5 ms

Ich gehe davon aus, dass Azure für den gehosteten Dienst eine Art Datenbankstatistik bietet. Sie sollten diese prüfen und bewerten, was geändert werden muss.

Überprüfen Sie zudem die URL /sidekiq Ihrer Installation, um festzustellen, ob keine Warteschlangenkonflikte die Datenbank blockieren.

Das haben wir als Erstes überprüft. Unsere Instanz verfügt über:

  • 8 Kerne (~16,18 % Auslastung, Spitzen bis 60 %)
  • 40 GB RAM (~60 % belegt, keine Spitzen)
  • 2244 verfügbare IOPS (~2,5 % Auslastung, Spitzen bis 24 %)

Wie bereits erwähnt, haben wir die in Ihrer postgres.10.template.yml beschriebene Konfiguration verwendet. Alles andere ist auf den Standardwerten. Es scheint, als müssten wir uns das noch einmal genauer ansehen.

Sidekiq sieht im Moment gut aus. 0 beschäftigt, 0 in der Warteschlange, 0 Wiederholungen, 1 geplant, 0 tot. Die Job-Liste ist derzeit leer.

Zusammenfassend lässt sich sagen: Als Erstes werden wir die PostgreSQL-Konfiguration überprüfen, da es einige Optimierungen gibt, die wir anwenden könnten. Falls das nicht hilft, sollten wir eine Aufrüstung der PostgreSQL-Instanz und/oder eine vollständige Vakuierung in Betracht ziehen.

Vielen Dank für Ihre bisherige Zeit und ein schönes Wochenende!
Mit freundlichen Grüßen
Sascha

Wenn der Rechner über 40 GB RAM verfügt, sind die Standardeinstellungen in der Datei postgres.10.template.yml nicht mehr geeignet, wie in der Datei samples/standalone.yml ausgeführt wird:

Hallo,

vielen Dank für Ihre Antwort. Bei der Nutzung einer PostgreSQL-Instanz auf Azure gibt es einige Einschränkungen. Bestimmte Einstellungen wie effective_cache_size, max_connections, maintenance_worker_mem oder shared_buffers können nicht geändert werden.

Zum Zeitpunkt der Erstellung dieser Supportanfrage nutzten wir die „General Purpose“-Ebene, die uns zwar 40 GB RAM zur Verfügung stellte, aber nur 1 GB für shared_buffers und 2,5 GB für effective_cache_size bot.

Seit gestern haben wir auf die „Memory Optimized“-Ebene umgestellt, was den RAM auf 80 GB verdoppelt hat, sowie shared_buffers auf 2 GB und effective_cache_size auf 5 GB erhöht hat.

work_mem, eine Einstellung, die wir anpassen können, ist derzeit auf 128 MB gesetzt, da wir keine Einträge für temporäre Dateien (temporary file) in unseren Logs finden.

Das Interessante war, dass die CPU- und IOPS-Auslastung sofort nach dem Wechsel der Ebene sank, ohne dass die Anzahl der vCores oder der Speicher erhöht wurde. Das deutet eindeutig darauf hin, dass das Problem durch zu kleine Caches und Puffer verursacht wurde.

Trotzdem zeigen die Zusammenfassungsseiten einiger Benutzer (insbesondere von Mitarbeiter- oder Langzeitbenutzern) sowie die About-Seite noch immer lange Ladezeiten, aber es ist deutlich besser als zuvor (ca. 50 % der vorherigen Ladezeiten).

Mit freundlichen Grüßen

P.S.
Für diejenigen, die auf ähnliche Probleme stoßen und mehr Kontrolle über ihre PostgreSQL-Installation haben, könnten diese kleinen Anleitungen hilfreich sein:

Gut zu hören. Als nächster Schritt wäre zu prüfen, ob Sie mit einer 4-vCPU-Memory-Optimized-Instanz als Kostenoptimierung auskommen oder ob Sie den Betrieb selbst übernehmen.

Oh, wir laufen mit 8 vCores, was 80 GB RAM ergibt. shared_buffers sind aktuell auf 2 GB eingestellt, sollten aber für diese Stufe und vCore-Anzahl bei 16 GB liegen. Wir stehen jedoch in Kontakt mit dem Azure-Support, um das zu beheben.

P.S.
Wir nutzen bereits 16 GB für shared_buffers. Ich habe die Ausgabe von SELECT * FROM pg_settings WHERE name = 'shared_buffers'; falsch interpretiert. Die Einheit ist 8 KB.

Daher denke ich, dass dieses Thema geschlossen werden kann. Ich danke euch allen für eure Mühe und hoffe, dass wir gemeinsam mit dem Azure-Support in den nächsten Tagen eine bessere Leistung erzielen können.

P.P.S.
Entschuldigung @riking, ich habe dich missverstanden. Ich denke, wir sind mit 8 vCores gut aufgestellt, anstatt sie auf 4 zu reduzieren. Können wir es versuchen, sobald wir die angestrebte Leistung erreicht haben?