Miglioramento delle prestazioni delle istanze (Megatopics, dimensione del database e carico estremo)

Hi Discourse Community!

Recently I have been trying to improve the performance of my Discourse installation and clean up a little since my site has been growing exponentially lately.

I have identified two issues, searched about them here but I don’t see a clear answer for some specifics, so I hope that this doesn’t represent much of a bother to anyone.

The first issue I have is the DB Size, which is pretty big. I’m running a 4GB Mem/80GB Disk instance on Digital Ocean and the DB is choking the disk size already. I do believe that eventually I will have to move it (if so, how?) but maybe I’m doing something wrong, following Sam’s Help I exported the following to make it easier:


table_name                  | row_estimate | table_size | index_size | total_size
--------------------------------------------------------------------------
post_timings                | 155307152    | 8004 MB    | 16 GB      | 24 GB
posts                       | 2257277      | 2432 MB    | 4810 MB    | 7242 MB
post_search_data            | 2279749      | 1992 MB    | 769 MB     | 2761 MB
user_actions                | 6549714      | 570 MB     | 2189 MB    | 2759 MB
topic_views                 | 8843734      | 444 MB     | 1494 MB    | 1937 MB
user_visits                 | 569317       | 33 MB      | 1892 MB    | 1925 MB
notifications               | 1482664      | 465 MB     | 914 MB     | 1379 MB
topic_users                 | 4821392      | 500 MB     | 449 MB     | 949 MB
top_topics                  | 47437        | 28 MB      | 773 MB     | 802 MB
user_auth_token_logs        | 1690555      | 515 MB     | 133 MB     | 648 MB
post_actions                | 1610428      | 145 MB     | 367 MB     | 512 MB
post_revisions              | 113187       | 396 MB     | 9312 kB    | 406 MB
topic_links                 | 605525       | 135 MB     | 254 MB     | 389 MB
topics                      | 56970        | 104 MB     | 227 MB     | 331 MB
web_hook_events             | 107760       | 295 MB     | 10 MB      | 306 MB
post_stats                  | 1955191      | 151 MB     | 97 MB      | 248 MB
directory_items             | 13026        | 1312 kB    | 157 MB     | 158 MB
incoming_links              | 812553       | 73 MB      | 82 MB      | 155 MB
post_replies                | 1111686      | 69 MB      | 71 MB      | 139 MB
topic_link_clicks           | 806821       | 54 MB      | 43 MB      | 97 MB
draft_sequences             | 654989       | 36 MB      | 48 MB      | 84 MB
topic_search_data           | 54056        | 40 MB      | 24 MB      | 65 MB
stylesheet_cache            | 901          | 57 MB      | 200 kB     | 57 MB
user_profile_views          | 204427       | 15 MB      | 30 MB      | 46 MB
quoted_posts                | 223337       | 18 MB      | 23 MB      | 41 MB
poll_votes                  | 142349       | 13 MB      | 20 MB      | 32 MB
users                       | 2211         | 2360 kB    | 29 MB      | 32 MB
given_daily_likes           | 252806       | 12 MB      | 16 MB      | 28 MB
scheduler_stats             | 115081       | 17 MB      | 4736 kB    | 21 MB
user_histories              | 30331        | 8848 kB    | 10040 kB   | 18 MB
reviewables                 | 16263        | 10032 kB   | 8344 kB    | 18 MB
optimized_images            | 34463        | 8088 kB    | 10 MB      | 18 MB
post_uploads                | 73123        | 4104 kB    | 13 MB      | 17 MB
uploads                     | 18897        | 5088 kB    | 9080 kB    | 14 MB
email_logs                  | 23224        | 4024 kB    | 9960 kB    | 14 MB
post_custom_fields          | 11043        | 3192 kB    | 9328 kB    | 12 MB
search_logs                 | 68429        | 7480 kB    | 4776 kB    | 12 MB
user_badges                 | 37176        | 2920 kB    | 5008 kB    | 7928 kB
unsubscribe_keys            | 14820        | 3352 kB    | 4480 kB    | 7832 kB
user_auth_tokens            | 5328         | 2536 kB    | 3608 kB    | 6144 kB
reviewable_scores           | 14681        | 3144 kB    | 2768 kB    | 5912 kB
reviewable_histories        | 31482        | 2976 kB    | 2616 kB    | 5592 kB
poll_options                | 20886        | 2560 kB    | 2552 kB    | 5112 kB
skipped_email_logs          | 11164        | 2528 kB    | 2328 kB    | 4856 kB
topic_allowed_users         | 21933        | 1424 kB    | 1872 kB    | 3296 kB
user_uploads                | 19038        | 1040 kB    | 1688 kB    | 2728 kB
user_stats                  | 2211         | 1888 kB    | 160 kB     | 2048 kB
drafts                      | 1324         | 1424 kB    | 368 kB     | 1792 kB
user_custom_fields          | 7467         | 688 kB     | 1064 kB    | 1752 kB
application_requests        | 11244        | 792 kB     | 528 kB     | 1320 kB
topic_tags                  | 10257        | 696 kB     | 528 kB     | 1224 kB
user_associated_accounts    | 670          | 1032 kB    | 184 kB     | 1216 kB
user_profiles               | 2211         | 424 kB     | 720 kB     | 1144 kB
email_tokens                | 3439         | 480 kB     | 528 kB     | 1008 kB
polls                       | 4030         | 520 kB     | 408 kB     | 928 kB
user_search_data            | 2215         | 376 kB     | 520 kB     | 896 kB
topic_custom_fields         | 2738         | 280 kB     | 568 kB     | 848 kB
group_users                 | 4364         | 344 kB     | 448 kB     | 792 kB
plugin_store_rows           | 2090         | 488 kB     | 296 kB     | 784 kB
incoming_referers           | 3779         | 352 kB     | 424 kB     | 776 kB
user_avatars                | 2210         | 208 kB     | 560 kB     | 768 kB
web_crawler_requests        | 1389         | 264 kB     | 440 kB     | 704 kB
group_histories             | 2210         | 272 kB     | 416 kB     | 688 kB
user_emails                 | 2218         | 224 kB     | 376 kB     | 600 kB
user_archived_messages      | 3019         | 240 kB     | 232 kB     | 472 kB
user_options                | 2218         | 384 kB     | 72 kB      | 456 kB
topic_allowed_groups        | 2098         | 128 kB     | 216 kB     | 344 kB
schema_migration_details    | 994          | 192 kB     | 88 kB      | 280 kB
group_mentions              | 933          | 104 kB     | 152 kB     | 256 kB
categories                  | 23           | 96 kB      | 112 kB     | 208 kB
google_user_infos           | 314          | 136 kB     | 72 kB      | 208 kB
theme_fields                | 24           | 168 kB     | 32 kB      | 200 kB
category_users              | 569          | 64 kB      | 136 kB     | 200 kB
javascript_caches           | 8            | 112 kB     | 64 kB      | 176 kB
incoming_domains            | 701          | 80 kB      | 96 kB      | 176 kB
groups                      | 51           | 120 kB     | 48 kB      | 168 kB
category_tag_stats          | 173          | 48 kB      | 104 kB     | 152 kB
tag_search_data             | 109          | 64 kB      | 72 kB      | 136 kB
schema_migrations           | 994          | 88 kB      | 48 kB      | 136 kB
topic_embeds                | 218          | 80 kB      | 56 kB      | 136 kB
badges                      | 51           | 80 kB      | 48 kB      | 128 kB
translation_overrides       | 170          | 72 kB      | 48 kB      | 120 kB
invites                     | 21           | 56 kB      | 64 kB      | 120 kB
user_api_keys               | 4            | 48 kB      | 64 kB      | 112 kB
category_search_data        | 20           | 48 kB      | 64 kB      | 112 kB
tags                        | 109          | 56 kB      | 48 kB      | 104 kB
screened_ip_addresses       | 9            | 48 kB      | 48 kB      | 96 kB
user_second_factors         | 26           | 48 kB      | 48 kB      | 96 kB
oauth2_user_infos           | 4            | 48 kB      | 48 kB      | 96 kB
site_settings               | 165          | 64 kB      | 32 kB      | 96 kB
api_keys                    | 1            | 48 kB      | 48 kB      | 96 kB
category_featured_topics    | 123          | 48 kB      | 48 kB      | 96 kB
screened_emails             | 4            | 48 kB      | 48 kB      | 96 kB
screened_urls               | 1            | 48 kB      | 48 kB      | 96 kB
topic_groups                | 245          | 56 kB      | 32 kB      | 88 kB
muted_users                 | 103          | 40 kB      | 48 kB      | 88 kB
tag_group_permissions       | 11           | 40 kB      | 48 kB      | 88 kB
tag_users                   | 8            | 40 kB      | 48 kB      | 88 kB
child_themes                | 6            | 40 kB      | 48 kB      | 88 kB
category_tags               | 9            | 40 kB      | 48 kB      | 88 kB
topic_timers                | 15           | 40 kB      | 48 kB      | 88 kB
ignored_users               | 10           | 40 kB      | 48 kB      | 88 kB
group_requests              | 0            | 24 kB      | 64 kB      | 88 kB
user_warnings               | 7            | 40 kB      | 48 kB      | 88 kB
email_change_requests       | 64           | 56 kB      | 32 kB      | 88 kB
web_hooks                   | 1            | 72 kB      | 16 kB      | 88 kB
custom_emojis               | 132          | 56 kB      | 32 kB      | 88 kB
color_scheme_colors         | 110          | 56 kB      | 32 kB      | 88 kB
tag_group_memberships       | 192          | 48 kB      | 32 kB      | 80 kB
category_custom_fields      | 17           | 48 kB      | 32 kB      | 80 kB
themes                      | 10           | 48 kB      | 32 kB      | 80 kB
badge_types                 | 3            | 48 kB      | 32 kB      | 80 kB
onceoff_logs                | 39           | 48 kB      | 32 kB      | 80 kB
category_tag_groups         | 8            | 40 kB      | 32 kB      | 72 kB
group_archived_messages     | 56           | 40 kB      | 32 kB      | 72 kB
category_groups             | 3            | 40 kB      | 32 kB      | 72 kB
push_subscriptions          | 12           | 48 kB      | 16 kB      | 64 kB
tag_groups                  | 10           | 48 kB      | 16 kB      | 64 kB
theme_settings              | 6            | 48 kB      | 16 kB      | 64 kB
ar_internal_metadata        | 1            | 48 kB      | 16 kB      | 64 kB
backup_metadata             | 6            | 48 kB      | 16 kB      | 64 kB
user_fields                 | 9            | 48 kB      | 16 kB      | 64 kB
remote_themes               | 7            | 48 kB      | 16 kB      | 64 kB
badge_groupings             | 5            | 48 kB      | 16 kB      | 64 kB
web_hook_event_types        | 10           | 48 kB      | 16 kB      | 64 kB
user_security_keys          | 0            | 8192 bytes | 56 kB      | 64 kB
color_schemes               | 11           | 48 kB      | 16 kB      | 64 kB
permalinks                  | 0            | 24 kB      | 32 kB      | 56 kB
incoming_emails             | 0            | 8192 bytes | 48 kB      | 56 kB
post_action_types           | 8            | 40 kB      | 16 kB      | 56 kB
web_hook_event_types_hooks  | 1            | 40 kB      | 16 kB      | 56 kB
watched_words               | 0            | 24 kB      | 32 kB      | 56 kB
user_exports                | 0            | 24 kB      | 16 kB      | 40 kB
github_user_infos           | 0            | 8192 bytes | 24 kB      | 32 kB
backup_draft_posts          | 0            | 8192 bytes | 24 kB      | 32 kB
categories_web_hooks        | 0            | 16 kB      | 16 kB      | 32 kB
theme_translation_overrides | 0            | 8192 bytes | 24 kB      | 32 kB
single_sign_on_records      | 0            | 8192 bytes | 24 kB      | 32 kB
post_reply_keys             | 0            | 0 bytes    | 24 kB      | 24 kB
backup_draft_topics         | 0            | 0 bytes    | 24 kB      | 24 kB
user_open_ids               | 0            | 8192 bytes | 16 kB      | 24 kB
post_details                | 0            | 8192 bytes | 16 kB      | 24 kB
message_bus                 | 0            | 8192 bytes | 16 kB      | 24 kB
anonymous_users             | 0            | 0 bytes    | 24 kB      | 24 kB
group_custom_fields         | 0            | 8192 bytes | 16 kB      | 24 kB
topic_invites               | 0            | 0 bytes    | 24 kB      | 24 kB
shared_drafts               | 0            | 0 bytes    | 24 kB      | 24 kB
instagram_user_infos        | 0            | 8192 bytes | 8192 bytes | 16 kB
reviewable_claimed_topics   | 0            | 0 bytes    | 16 kB      | 16 kB
user_field_options          | 0            | 8192 bytes | 8192 bytes | 16 kB
embeddable_hosts            | 0            | 8192 bytes | 8192 bytes | 16 kB
invited_groups              | 0            | 0 bytes    | 8192 bytes | 8192 bytes
developers                  | 0            | 0 bytes    | 8192 bytes | 8192 bytes
tags_web_hooks              | 0            | 0 bytes    | 8192 bytes | 8192 bytes
groups_web_hooks            | 0            | 0 bytes    | 8192 bytes | 8192 bytes
badge_posts                 | 0            | 0 bytes    | 0 bytes    | 0 bytes

(on the other hand, the /var/discourse/shared/standalone/postgres_data/base folder is over 47GB)

Can it be reduced somehow or is it logical given the size of some topics? (more details below).

The other issue maaaay be related, I believe, which is that I keep getting the famous " Due to extreme load, this is temporarily being shown to everyone as a logged out user would see it" I read on a post that increasing Unicorn Workers may be an option (never touched that, honestly havent found how to do it or how viable it is without endangering the whole installation). As a note we do have quite some topics with more than 10k answers, so that may be a correlation between DB Size and Performance issues? (Throwing it out, not sure).

I wonder if there is some way of optimizing it (I found this one), either on the very same instance or recurring to something like a HA installation (which I don’t know if it is supported), but I do believe that I’m jumping the gun in my ignorance. I do appreciate any help I could get.

As a note: I was using a swap file when the instance was smaller, I do believe it is disabled now (is there a way of verifying this?).

Thanks and sorry for the n00bness.

Quella tabella post_timings è un mostro. Possiamo fare qualcosa per troncarla, “abbreviarla” o “sintetizzarla” senza rompere nulla @sam?

Mini-aggiornamento: Ho provato a modificare le impostazioni di Unicorn Runners, ma non sono sicuro se esista una relazione core-per-worker o se sia una sorta di CPU condivisa, tipo CPU % x Second. Esiste una best practice in merito?

Inoltre, ho letto informazioni su PostgreSQL per capire come gestire la dimensione, ma, anche se ho un backup, non so come reagirà l’app nel lungo termine se procedo semplicemente a tagliare.

Modifica rapida: Ho rimosso il file di swap e ora sto analizzando come procedere con i 10.000+ argomenti. Approfitto dell’occasione per chiedere quanto siano pericolosi per il quadro generale (immagino che ci sia un certo rischio dato il consiglio, ma se ci sono altri aspetti da considerare, mi piacerebbe apprenderli se possibile).

Anche io ho alcuni argomenti con oltre 10k risposte e vedo questo messaggio di tanto in tanto quando il sito è molto affollato.

Vi sconsiglio vivamente di sovrascrivere le impostazioni predefinite di Discourse, che chiudono automaticamente gli argomenti con oltre 10k risposte. C’è un motivo per cui questa impostazione è attiva di default. :scream:

Oltre a ciò, il problema della tabella post_timings di dimensioni massicce è sotto la nostra attenzione :satellite_antenna: e stiamo attualmente valutando modi per gestirlo, forse anche nella versione 2.5 corrente cc @sam @eviltrout

Sento che serva una conferma triplice, con il pulsante finale che recita “Sono ok con il fatto che succedano cose brutte”.

C’è qualcuno che riesce a far funzionare davvero i megatopic?

Abbiamo circa 80 megatemi attivi continuamente (128k post nel più grande).

A volte si verificano alcuni problemi 502 (magari correlati a questo, non posso dirlo), ma tutto funziona senza intoppi da quando abbiamo impostato il parametro db_shared_buffers su un valore superiore alla dimensione del database.

Questa è un’idea profondamente sbagliata e dovresti chiudere quei topic a favore di topic più piccoli, annuali o stagionali. Vedi

Ho un sito con una manciata di argomenti mega da oltre 100K post. Ho detto loro che era un errore, ma li volevano comunque. Si stanno lamentando di problemi di prestazioni. Spero di poter presto tornare al valore predefinito di 10K.

Mi ha comunque permesso di imparare alcune cose sull’ottimizzazione del database, quindi è un vantaggio. :slight_smile:

Capisco cosa vuoi dire, ma devo anche ammettere che può essere scomodo dividere un topic per anni, specialmente perché abbiamo molte conversazioni incentrate sulle persone.

Immagina un topic su Trump in generale o uno sugli Stati Uniti in generale. Nel nostro forum abbiamo un topic su uno degli ex presidenti del nostro club, uno per il presidente attuale, uno per ogni giocatore della squadra di calcio. Capisci il punto. È facile dividere altri topic per stagioni, ma non questi. Certo, non è impossibile, ma piuttosto poco pratico.

Immagina una categoria su Trump in generale o sugli Stati Uniti in generale.

Nessuno leggerà più di 10.000 messaggi in un argomento di seguito. Proprio non lo fanno. A un certo punto, puoi semplicemente fare un respiro e ricominciare da capo. Sospetto che questi argomenti siano più simili a una chat che a una discussione, e che poche persone leggano cosa è successo ieri, figuriamoci la settimana scorsa, il mese scorso o l’anno scorso.

Ok, ma la mia risposta a questo è

… stai scegliendo di causarti un notevole dolore per “motivi”.

Ecco una query per l’esploratore di dati che replica la query utilizzata per ottenere una pagina di post:

-- [params]
-- int :topic_id = 107216
-- int :offset = 10000

SELECT "posts"."id" FROM "posts" 
WHERE ("posts"."deleted_at" IS NULL) 
AND "posts"."topic_id" = :topic_id
AND "posts"."post_type" IN (1,2,3) ORDER BY "posts"."sort_order" ASC LIMIT 20 
OFFSET :offset

Ecco un argomento normale:

Limit  (cost=1911.35..1915.38 rows=1 width=8) 

Ecco un argomento enorme:

Limit  (cost=37475.88..37550.83 rows=20 width=8)

:+1:

Vi credo, è solo che i nostri utenti sono abituati a funzionare così e ci vorrà un po’ di sforzo per cambiare… ma è fattibile.

In relazione a questo, stavo appena leggendo il post di @codinghorror Natural breakpoints or "chapters" for long topics? - #53 by codinghorror e ho pensato che una sorta di sommario, ma solo per i topic, sarebbe una bella soluzione per poter raccogliere e rendere visibile una sequenza di topic mentre si naviga e si risponde all’interno di un unico thread.

Non fraintendete: ho fatto quel lavoro non per convincere voi, ma per convincere il mio cliente con oltre 120K argomenti di post che si sta lamentando delle prestazioni!

Spero che possa essere d’aiuto anche a voi. Buona fortuna! :wink:

:clinking_glasses:

Molto utile! Grazie per aver condiviso!

Abbiamo piani concreti a breve termine per ottimizzare la tabella post_timings, ma i megatopic rimarranno una fonte di notevoli problemi per molti, molti anni.

:warning: e ricordate che questo avviene dopo il ottimo lavoro svolto circa un anno fa da @tgxworld per ridurre l’entità complessiva del lavoro che svolgiamo sui megatopic, passando essenzialmente a una “modalità a basso consumo” per questi argomenti in modo che facciano meno male.

Ma non illudetevi: i megatopic colpiscono ancora DURAMENTE. :boom::boxing_glove:

Seguendo i vostri suggerimenti e mentre cerco di chiarire le altre domande (riconoscendo che voi state lavorando sulla tabella post_timings), procedo a ripristinare le impostazioni predefinite per la dimensione dei topic (scusandomi per la mia stupidità, perché no).

Con questo in mente, ho alcune domande che spero possiate rispondere:

  1. Una volta ripristinata l’impostazione, quei topic verranno chiusi e ne verranno creati di nuovi. Tuttavia, l’esistenza di quei vecchi topic grandi è pericolosa per l’intero sito? Cioè, dovrei “dividerli” X volte in topic più piccoli o, fintanto che non sono attivi, va bene così?

  2. Ho visto il dibattito sollevato da @Paracelsus riguardo alla comodità per gli utenti. A questo proposito, vorrei chiedere se sarebbe possibile avere un’impostazione per “Riattivare automaticamente i topic chiusi a causa della dimensione massima del topic”. Cioè, quando un mega-topic viene chiuso automaticamente, sarebbe possibile che ne apra un altro con lo stesso autore, lo stesso titolo (con un numero alla fine del titolo, magari) e come unico contenuto un link al precedente? (Aggiungendo il link al nuovo topic in quello chiuso).

So che è un po’ contorto e forse non desiderato da tutti (ecco perché lo propongo come impostazione opzionale), ma per siti ad alto traffico con topic rilevanti potrebbe essere utile, penso. Che ne pensate?

È come chiedere: “dovremmo incoraggiare le persone a fumare sigarette comprando loro automaticamente un nuovo pacchetto quando finiscono?” :wink:

No, a meno che non ricevano molto traffico, il quale non dovrebbe accadere se sono chiusi, a quanto pare? Vedi come va, ma fermare il flusso degli argomenti mega attivi è il passo zero, quindi sei sulla buona strada :+1:

Solo un aggiornamento… Stiamo cercando ora di gestire questi mega-argomenti dividendoli in blocchi da 10.000 post ciascuno. Tuttavia, il sistema non sembra voler accettare la nostra strategia :sweat_smile::

Ricevo un “502 Bad Gateway” quando seleziono almeno 8.000 post alla volta e li sposto in un nuovo argomento (non ho ancora provato con quantità minori di post). C’è un modo per aumentare la capacità o un altro/ migliore modo per raggiungere questo obiettivo? @codinghorror @pfaffman

La soluzione è farlo dalla console di Rails, ma non so immediatamente come farlo.

Qualcosa del genere:

old_topic=1
new_topic=2
Posts.where(topic_id: old_topic).where("post_number > 10000 and post_number < 20000").update_all(topic_id: new_topic, post_number=...)

ma… penso che tu possa dover inserire questo in un ciclo per generare i nuovi numeri dei post. Dovresti testare la tua soluzione su un sito di staging. Se sbagli qualcosa, ti troverai in un bel guaio.

Se questo non ti basta per capire come farlo, probabilmente dovrai pubblicare un messaggio in Marketplace. Ma scommetto che nessuno leggerà i vecchi post comunque, e che dovresti semplicemente chiuderli e lasciarli così, magari anche cancellandoli o rimuovendoli dall’elenco, a meno che tu non pensi che abbiano un valore SEO.