Tempi di caricamento lunghi per la pagina riepilogo utente con database lento

Ciao,

Stiamo riscontrando tempi di caricamento molto elevati nell’accesso alla pagina di riepilogo di un utente. Sembra che il caricamento del riepilogo richieda più tempo quanto più un utente è attivo sul nostro sito. Il che, sì, sembra piuttosto ovvio, ma la differenza nei tempi di caricamento sul nostro sito è enorme.
Quindi, il caricamento della pagina di riepilogo di un “nuovo” utente (con alcune settimane di attività) richiede circa 1 secondo, mentre il caricamento della pagina di un utente con attività giornaliera da anni richiede fino a 30-40 secondi.

Abbiamo quindi controllato il database e siamo rimasti piuttosto colpiti dalle dimensioni della tabella topic_views (inclusi gli indici), che ammontano a 62 GB.

Ecco le nostre 7 tabelle più grandi:

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

Per testare questa situazione, abbiamo selezionato l’ID di un utente di cui sappiamo che il caricamento del riepilogo richiede molto tempo e abbiamo eseguito un conteggio con quell’ID sulla tabella topic_views. Questa query ha richiesto quasi lo stesso tempo necessario per caricare il riepilogo dell’utente. Quindi, la parte topics viewed è responsabile di questo ritardo.

Come spiegato in argomenti precedenti, abbiamo aggiornato un vecchio sito basato su Discourse (v1.2.4 + modifiche) alla versione v2.4.0-beta.2 e ora stiamo eseguendo Discourse v2.4.0-beta6. Quindi potrebbe esserci qualche dato residuo. Ma non sappiamo cosa possa essere eliminato.

A questo punto siamo piuttosto incerti su cosa fare o modificare successivamente. La nostra installazione è completamente ospitata su Azure, utilizzando un’istanza esterna di Azure Database for PostgreSQL, e abbiamo applicato la configurazione descritta nel file postgres.10.template.yml. Non sappiamo nemmeno se le dimensioni della tabella topic_views (specialmente l’indice) siano “troppo grandi” rispetto alle altre tabelle o se siano piuttosto normali.

Qualsiasi suggerimento, riflessione o idea sarà apprezzato.

Cordiali saluti,
Sascha Hofmann

P.S.
Ho dimenticato di menzionare che, a causa di ciò, stiamo riscontrando diversi errori 502 (visualizzati direttamente sul sito, quindi non errori di pagina nginx o gateway applicativo) durante il caricamento di /u/<username>/summary.json.

Lo stai visualizzando come amministratore/staff o come anonimo? La visualizzazione per lo staff è molto più costosa.

Non fa alcuna differenza se visualizzo /u/<username>/summary come amministratore/staff o con il mio account utente normale. Abbiamo anche attivato l’opzione “nascondi i profili utente al pubblico”, quindi i profili utente non sono visibili per gli anonimi (l’ho disattivata per i test, ma non cambia nulla, poiché anche i topic visualizzati sono presenti nella riepilogo).

Hai migrato, modificato o ricostruito lo stesso database più e più volte? È possibile che il tuo database necessiti di un VACUUM per aggiornare le statistiche. Query da 30 secondi sono ben al di fuori dell’intervallo normale che osserviamo nelle installazioni di Discourse (anche se ammettiamo che il tuo DB sia di grandi dimensioni).

VACUUM FULL vale la pena provarlo se puoi accettare un certo periodo di inattività.

Inoltre, il tuo database è su un’unità SSD veloce con MOLTA RAM? Questo è fondamentale.

Per sapere esattamente qual è il problema:

  1. Modifica il file app.yml e aggiungi la tua email di amministratore a DISCOURSE_DEVELOPER_EMAILS.

  2. Ricostruisci

  3. Carica la pagina lenta mentre sei loggato come l’utente impostato al punto 1.

  4. Condividi il risultato del mini-profiler

Condividi il contenuto di questa e della finestra espansa:

Lo abbiamo testato diverse volte, ma sempre con una copia fresca del vecchio dataset. Dopo un paio di settimane e non appena siamo stati certi di aver annullato con successo le modifiche del precedente proprietario, abbiamo eseguito l’aggiornamento e la migrazione una sola volta.

È sicuramente un tentativo che vale la pena fare, ma non sono sicuro di quanto tempo richiederà. Tuttavia, sì, dovremmo considerare un vacuum completo. Soprattutto perché abbiamo avuto alcuni problemi con il database precedente già in passato.

Sì. Tutti i dati sono archiviati su un server SSD e supportati da 40 GB di RAM (di cui circa il 60% è utilizzato complessivamente, senza raggiungere plateau al 100% anche sotto carichi elevati).

Grazie per questo consiglio, ci proverò.
Dato che utilizziamo la nostra immagine Docker, dove app.yml manca, dovremmo ottenere lo stesso comportamento aggiungendo l’indirizzo/e email a developer_emails nel file discourse.conf.

Puoi accedere alla console di Rails e utilizzare Developers.create!(user_id: 123) dove 123 è il tuo ID utente.

Purtroppo non funziona (sì, ho già sostituito 123 prima :slight_smile:) :

discourse@2d5c3bf04550:~$ rails console --environment=production
Caricamento dell'ambiente di produzione (Rails 6.0.0)
irb(main):001:0> Developers.create!(user_id: 123)
Traceback (most recent call last):
        1: from (irb):1
NameError (costante Developers non inizializzata)

Un altro approccio:

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>': costante Developers non inizializzata (NameError)
discourse@2d5c3bf04550:~$ cat make_me_dev.rb
Developers.create!(user_id: 123)

Proverò il metodo discourse.conf e fornirò i dati richiesti il prima possibile.

Grazie per i consigli finora!

Bene, è per questo che diciamo sempre alle persone di utilizzare il metodo ufficiale e supportato per installare Discourse, così quando serve aiuto possiamo intervenire utilizzando strumenti standard.

Sì, forse è perché stiamo utilizzando supervisord per avviare tutti i processi.

Comunque, ecco l’output che hai richiesto (contenuto HTML compresso):
_u_x_strom_summary.json-13498.2ms-ProfilingResults.zip (94,5 KB)

Questa richiesta ha richiesto 13 secondi, ma ho dovuto caricare il sito due volte. Ancora una volta, il primo tentativo ha impiegato troppo tempo, causando un errore 502. Quindi forse alcune cose erano già state memorizzate nella cache.

Ci sono voluti più di 13 secondi per eseguire 51 query SQL. Il tuo database è seriamente mal configurato o sottodimensionato.

I principali responsabili
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; 

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

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

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

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

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

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

Tempo: 811,5 ms

Immagino che Azure offra delle statistiche sul database per il servizio ospitato; devi controllarle e valutare cosa modificare.

Controlla anche l’URL /sidekiq sulla tua installazione per verificare se non ci siano conflitti nella coda che tengono il database occupato.

È proprio la prima cosa che abbiamo verificato. La nostra istanza ha:

  • 8 core (~16,18% di utilizzo, con picchi fino al 60%)
  • 40 GB di RAM (~60% utilizzati, senza picchi)
  • 2244 IOPS disponibili (~2,5% di utilizzo, con picchi fino al 24%)

Come detto, abbiamo utilizzato la configurazione descritta nel tuo postgres.10.template.yml. Tutto il resto è impostato sui valori predefiniti. Sembra che dovremmo rivedere la questione.

Al momento Sidekiq funziona bene. 0 occupati, 0 in coda, 0 tentativi di riprova, 1 pianificato, 0 morti. L’elenco dei lavori è attualmente vuoto.

Quindi, per trarre una prima conclusione: inizialmente verificheremo la configurazione di PostgreSQL, poiché ci sono alcune ottimizzazioni che potremmo applicare. Se ciò non funzionerà, dovremmo prendere in considerazione l’aggiornamento dell’istanza PostgreSQL e/o eseguire una vacuum completa.

Grazie per il tempo dedicatoci finora e buon fine settimana!
Cordiali saluti
Sascha

Se la macchina dispone di 40 GB di RAM, le impostazioni predefinite in postgres.10.template.yml non sono più appropriate, come indicato in samples/standalone.yml:

Ciao,

grazie per la tua risposta. Esistono alcune limitazioni nell’utilizzo di un’istanza PostgreSQL su Azure. Non è possibile modificare alcune impostazioni come effective_cache_size, max_connections, maintenance_worker_mem o shared_buffers.

Al momento della creazione di questa richiesta di supporto, stavamo utilizzando il livello “General Purpose”, che ci offriva 40 GB di RAM ma solo 1 GB di shared_buffers e 2,5 GB di effective_cache_size.

Da ieri abbiamo cambiato livello passando a “Memory Optimized”, che ha raddoppiato la RAM a 80 GB, portando shared_buffers a 2 GB e effective_cache_size a 5 GB.

work_mem, un’impostazione che possiamo regolare, è attualmente impostato a 128 MB, poiché non rileviamo voci relative a temporary file nei nostri log.

La cosa interessante è che non appena abbiamo cambiato livello, l’utilizzo di CPU e IOPS è diminuito senza aumentare i vCore né lo spazio di archiviazione. Questo conferma che avevamo un problema causato da cache e buffer troppo piccoli.

Ancora oggi osserviamo tempi di caricamento lunghi per le pagine di riepilogo di alcuni utenti (in particolare gli utenti staff o quelli con account di lunga data) o per la pagina about, ma la situazione è nettamente migliorata rispetto a prima (i tempi di caricamento sono circa il 50% di quelli precedenti).

Cordiali saluti,

P.S.
Per chi si trova ad affrontare problemi simili e ha maggiore controllo sulla propria installazione di PostgreSQL, queste piccole guide potrebbero essere utili:

Bene da sapere. I prossimi passi consistono nel verificare se è possibile utilizzare un’istanza Memory-Optimized con 4 vCPU per ottimizzare i costi, oppure passare alla gestione autonoma.

Oh, stiamo eseguendo 8 vCore, il che corrisponde a 80 GB di RAM. shared_buffers è impostato a 2 GB, ma per questo livello e questo numero di vCore dovrebbe essere a 16 GB. Tuttavia, siamo in contatto con il supporto Azure per risolvere il problema.

P.S.
Siamo già su shared_buffers da 16 GB. Ho interpretato male l’output di SELECT * FROM pg_settings WHERE name = 'shared_buffers';. L’unità è 8kb.

Quindi penso che questo argomento possa essere chiuso. Vi ringrazio per il vostro impegno e spero che, insieme al supporto Azure, possiamo ottenere prestazioni migliori nei prossimi giorni.

P.P.S.
Scusa @riking, ho frainteso. Penso che possiamo procedere con 8 vCore invece di ridurli a 4. Possiamo provarlo non appena avremo raggiunto le prestazioni che stiamo cercando.