Misskeyで学ぶPostgresパフォーマンスチューニング入門
みすてむず いず みすきーしすてむず というMisskeyサーバーなどを運営しています。ねこかんです。
この記事はMisskey Advent Calendar 2024 1日目の記事です。
Misskeyサーバーを運営していて参加者が増えてくると、最初は俊敏に動いていたMisskeyがゆっくりになってしまうことがあります。
サーバーのスペックを上げていけば問題が解決する場合もありますが、それはサーバー全体の性能を使い切った結果なのでしょうか?
マネージドなDBを提供してくれているサービスなら、この辺は命をかけてやってくれてると思います。
ですが、自分で建てているDockerやVPSで動いているPostgresは放っておくと適当なところで自分の限界を定めてしまうようです。
ねこかんはインフラしょしんしゃのねこなので、手探りで調べた結果をまとめていこうと思います。
やったこと
/etc/postgresql/15/main/postgresql.conf
をいじくり回す、及びその根拠っぽいのを探す
--- /usr/share/postgresql/15/postgresql.conf.sample 2024-11-12 14:06:10.000000000 +0000
+++ /etc/postgresql/15/main/postgresql.conf 2024-11-30 11:17:28.485458879 +0000
# - Memory -
-#shared_buffers = 128MB # min 128kB
+shared_buffers = 3GB # min 128kB
# (change requires restart)
#huge_pages = try # on, off, or try
# (change requires restart)
@@ -135,9 +135,9 @@
# Caution: it is not advisable to set max_prepared_transactions nonzero unless
# you actively intend to use prepared transactions.
-#work_mem = 4MB # min 64kB
+work_mem = 512MB # min 64kB
#hash_mem_multiplier = 2.0 # 1-1000.0 multiplier on hash table work_mem
-#maintenance_work_mem = 64MB # min 1MB
+maintenance_work_mem = 128MB # min 1MB
#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem
#logical_decoding_work_mem = 64MB # min 64kB
#max_stack_depth = 2MB # min 100kB
@@ -392,7 +392,7 @@
# - Planner Cost Constants -
#seq_page_cost = 1.0 # measured on an arbitrary scale
-#random_page_cost = 4.0 # same scale as above
+random_page_cost = 1.1 # same scale as above
#cpu_tuple_cost = 0.01 # same scale as above
#cpu_index_tuple_cost = 0.005 # same scale as above
#cpu_operator_cost = 0.0025 # same scale as above
@@ -400,7 +400,7 @@
#parallel_tuple_cost = 0.1 # same scale as above
#min_parallel_table_scan_size = 8MB
#min_parallel_index_scan_size = 512kB
-#effective_cache_size = 4GB
+effective_cache_size = 4GB
#jit_above_cost = 100000 # perform JIT compilation if available
# and query more expensive than this;
@@ -615,7 +615,7 @@
#track_activities = on
#track_activity_query_size = 1024 # (change requires restart)
#track_counts = on
-#track_io_timing = off
+track_io_timing = on
#track_wal_io_timing = off
#track_functions = none # none, pl, all
#stats_fetch_consistency = cache
@@ -634,7 +634,7 @@
# AUTOVACUUM
#------------------------------------------------------------------------------
-#autovacuum = on # Enable autovacuum subprocess? 'on'
+autovacuum = on # Enable autovacuum subprocess? 'on'
# requires track_counts to also be on.
#autovacuum_max_workers = 3 # max number of autovacuum subprocesses
# (change requires restart)
何をしているのか
どうやらPostgresはデフォルトではサーバーのスペックをフルで使い切るようになっていないようです。
そこで、明示的に各種パラメータの上限値を設定します。
Postgresは effective_cache_size + shared_buffers に指定した量までしか使わないらしいのです。
effective_cache_size
PostgreSQLがカーネルのディスクキャッシュとして利用可能なメモリ量を推定するために使用するそうです。サーバーの残りメモリ(通常、共有バッファ以外)を割り当てます。
推奨値: メモリの50~75%
shared_buffers
説明: PostgreSQLが使用する共有メモリの量を設定します。サーバーメモリの約25~40%を割り当てるのが一般的らしいです。
また、work_mem を明示的に指定することで、クエリごとに使って良いメモリ量を指定できるようです。
ところでVacuumってやったことあります?イメージとしてはデフラグみたいなやつでらしいです。
Windowsの眺めるのすきでした。ぽすぐれにあのブロック崩しみたいなやつはないのでたのしくないです。
autovacuum を on に指定すると勝手にやってくれます。オンにしましょう。
で、変わったのか?
なんか変わってなさそうに見える!なんでやねん!!!
このグラフのUsedのメモリが7GBぐらい使うところを見たかった。
ちなみにこのグラフを出してくれるくんはmackerelといいます。
mackerelはサーバーの統計情報をいい感じに収集してくれるSaaSで、フリープランでも24時間分のグラフが見れます。
なんかよさそうやん!って人はいれてみてください。
mackerel本体だけじゃなくて、mackerel-plugin-postgresやmackerel-plugin-redisなんかもあるのでどうぞ。
この記事をめちゃくちゃにらめっこしました。
ただ、アプリケーションがnodeでpostgresとの接続クライアントにpgを使っており、そうするとconnection数が1に見える(実際にはこのconnectionはメトリックを取っている接続で、実際にはidleのconnectionがワーカー数×10 いる)という罠にずっとかかっていました。
postgres.confの全体を眺めるとプランナーの調整などもできそうなので、そのあたりの調整でいい感じになるかもしれませんが、なにもわかりません。
Misskeyが重いのは1時間ごとの集計がやばいという説もねこのなかにあり、それをなんとかしたほうがはやいんじゃーという話とか、いろいろあります。
いちおう mackerel とかつかってグラフがビヨンビヨンしてるところは眺めつつ、設定をあれこれいじっていますが、
未だにどこがボトルネックになっているのかはっきりと掴めていません。
調査レポートを折りたたんで飛行機にして飛ばしたい気分です。だれかおしえてください。
ねこはねます。明日は くちばし さんがなにか書いてくれると思います
Discussion