1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ridgepoleを使ってPostgreSQLのFILLFACTORを設定した

Last updated at Posted at 2025-02-28

はじめに

Gakken LEAPで働いていますkoboriです。私が担当をしているプロダクトでは、Rails標準のマイグレーションではなく、Ridgepoleというgemを採用しています。私はこのプロダクトの担当に就いた際に初めてRidgepoleを使ったのですが、スキーマ定義を宣言的に記述することができ、非常に気に入っております。

日々の運用の中で、あるタイミングから時折スロークエリログが検知されるようになりました。対象は更新系のクエリで、書き込み性能の改善をする必要が出てきました。対象のWeb APIではINSERTよりUPDATE文が圧倒的に多いこと、RDSのメトリクスの数値から、HOT機能を活用するためにFILLFACTORの設定を行うことにしました。

そんな背景から、小ネタではありますが、今回はRidgepoleを使ってPostgreSQLのFILLFACTORを設定した時の話を書いていきます。

Ridgepoleについては、GithubのREADMEをご参照ください。

また、HOT及び、FILLFACTORについては、Let's Postgresの下記のシリーズを参考にしました。

FILLFACTORを設定する

まず、下記のクエリで現状の設定を確認し、reloptionsの値からFILLFACTORが設定されていないことを確認します。

SELECT relname, reloptions FROM pg_class WHERE relname = 'table_name';

次に、PostgreSQLのドキュメントを参照し、FILLFACTORの設定方法を確認します。
FILLFACTORの設定方法は、CREATE TABLE または、ALTER TABLE で設定することができます。今回は作成済みのテーブルに設定を追加するため、ALTER TABLEを使用することになります。

ここからが本稿の本題です。Ridgepoleを使ってテーブルオプションを設定していきます。

まずは、淡い期待を抱きつつ #create_tableの引数にFILLFACTORの設定を書いてみましたが、設定は反映されませんでした。
調べた限り、そもそもActiveRecordにテーブルオプションを設定するインターフェースが存在しないようで、別の方法を探すことにしました。

create_table :table_name, fillfactor: 90 do |t|
  # ...
end

過去に似たような事例がないかとRidgepoleのissuesを漁っている中で、#execute を使うことで今回のユースケースをカバーできるのではないか、ということが分かりました。余談ですが、READMEにも#execute に関する記載があり、見落としていたことが後になって分かりました。READMEはしっかり読まねばと猛省しました。

それでは #execute を使って設定をしていきます。

execute 'ALTER TABLE table_name SET (FILLFACTOR = 90)' do |c|
  # 既に設定済みの場合は実行をスキップする
  c.raw_connection.query(
    "SELECT relname, reloptions FROM pg_class WHERE relname = 'table_name'AND 'fillfactor=90' = ANY(reloptions)"
  ).each.size.zero?
end

これにより、テーブルオプションの設定が反映され、2回目以降の適用時にはスキップされるようになりました。

FILLFACTORに設定する値は、テーブルの更新頻度やデータ量を見て決めていく必要があります。設定する際はご注意ください。

また、今回紹介した書き方だと、 #execute を削除して適用しても、FILLFACTORの設定は削除されません。FILLFACTORの設定をリセットする場合は、下記のクエリを実行した上で、#execute の記述を削除する必要があります。明示的に値を100に設定するのも良いかもしれません。

ALTER TABLE table_name RESET (FILLFACTOR);

FILLFACTORの設定を運用中のテーブルに適用する際は、過去のデータに対してもFILLFACTORの設定を適用するか否かの判断をする必要があります。
過去のデータに対しても設定を適用する場合は、VACUUM FULLを実行することで設定を適用することができます。しかし、テーブルに対する排他的ロックが必要になる、余分なディスク容量が必要になる、などの注意点がありますので、実行をする際は慎重に検討をする必要があります。詳細は下記をご参照ください。

過去のデータに対して設定を適用する必要がない場合は、新たに作成されるページから設定が適用されるようです。

おわりに

経過観察中ではありますが、本対応を実施して以降、該当のWeb APIに起因するスロークエリログは検出されていません。事象が改善されない場合は、WAL書き込みの非同期化、パラメータのチューニングなど、次の対応を検討していく予定です。

エンジニア募集

Gakken LEAP では教育をアップデートしていきたいエンジニアを絶賛大募集しています。
ぜひお気軽にカジュアル面談へお越しください。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?