PostgreSQLのVACUUM(バキューム)とは?データベースの掃除でパフォーマンスを劇的に改善する仕組み
生徒
「PostgreSQLというデータベースを使い始めたのですが、最近動きが少し遅くなった気がします。バキューム(VACUUM)という掃除が必要だと聞いたのですが、掃除機のことですか?」
先生
「その通り!実はPostgreSQLというシステムは、データを削除したり書き換えたりしても、すぐには完全に消えない仕組みになっているんです。古いゴミが溜まると動きが重くなるので、バキューム、つまり掃除機をかけて綺麗にする必要があります。」
生徒
「パソコンの画面の中でゴミが溜まるなんて不思議ですね。プログラミングの経験が全くない私でも、その仕組みを理解できるでしょうか?」
先生
「もちろんです。例えば、ノートの書き間違いを消しゴムで消さずに、上からシールを貼って隠し続けている状態をイメージしてみてください。ページがどんどん厚くなってめくりにくくなりますよね。それを解決するのがVACUUMの役割です。」
1. PostgreSQLのVACUUMとは何か?
PostgreSQL(ポストグレスキューエル)というデータベース管理システムにおいて、VACUUM(バキューム)は非常に重要なメンテナンス作業です。日本語では「掃除」や「整理整頓」と訳すと分かりやすいでしょう。データベースは、長期間使っていると内部に「不要なデータ」がゴミのように溜まってしまいます。このゴミを放置すると、コンピュータが情報を探すスピードが遅くなり、結果としてウェブサイトやアプリの動作が重くなってしまいます。
なぜゴミが溜まるのかというと、PostgreSQLが採用している「マルチバージョン並行制御(MVCC)」という仕組みに理由があります。これは、誰かがデータを書き換えている最中でも、他の人が古いデータを見られるようにするための工夫です。しかし、その副作用として「もう誰も使わない古いデータ」がファイルの中に居座り続けてしまいます。VACUUMはこの居座ったゴミを見つけ出し、新しいデータが書き込めるように隙間を空ける作業なのです。
2. なぜ掃除が必要?「不要なデータ」が生まれる仕組み
まずは、データベースの中がどのようになっているか見てみましょう。ここでは例として、会員の年齢情報を更新する場合を考えます。コンピュータ未経験の方でも、紙の台帳を想像すれば簡単です。
例えば、次のような「users(利用者)」という名前の表があるとします。
id | name | age | email
---+----------+-----+-------------------
1 | 山田太郎 | 25 | taro@example.com
2 | 佐藤花子 | 30 | hanako@example.com
3 | 鈴木一郎 | 40 | ichiro@example.com
ここで、山田太郎さんが誕生日を迎えて「25歳から26歳」に情報を更新(アップデート)するとします。普通の感覚だと、25という数字を消しゴムで消して、その上に26と書くと思いますよね。しかし、PostgreSQLは違います。
PostgreSQLの動き:
1. 元の「25歳」のデータに「これはもう使わない」という印を付ける。
2. 新しく「26歳」というデータを別の場所に書き込む。
つまり、内部的には一時的にデータが2つ存在することになります。この「使わない印」がついた古いデータが、いわゆる「デッドタプル(死んだデータ)」と呼ばれるゴミです。
UPDATE users
SET age = 26
WHERE id = 1;
実行後の見た目上のデータはこうなります。
id | name | age | email
---+----------+-----+-------------------
1 | 山田太郎 | 26 | taro@example.com
2 | 佐藤花子 | 30 | hanako@example.com
3 | 鈴木一郎 | 40 | ichiro@example.com
しかし、データベースのファイルの中には、先ほどの「25歳」というゴミデータが残ったままです。これを何万回、何億回と繰り返すと、ファイルはゴミだらけになり、中身を確認するのに時間がかかるようになります。これが、動作が重くなる「パフォーマンス低下」の正体です。
3. VACUUMが実行する「3つの大切な仕事」
VACUUMの役割は、単にゴミを消すだけではありません。主に3つの重要な役割を担っています。
① 空きスペースの再利用(スペースの解放)
これが一番メインの役割です。先ほどの「25歳(古いデータ)」があった場所を、「ここは自由に使っていいよ!」という空き地に変えます。これにより、次に新しいデータが入ってきたときに、その空き地を再利用できるようになります。これを行わないと、ファイルはどこまでも巨大化し続けてしまいます。
② 統計情報の更新
データベースには「司令塔」のような機能があり、どのデータがどこにあるかを常に考えています。この司令塔が最適なルートでデータを探すためには、表に何件のデータがあるかという「統計情報」が必要です。VACUUMはこの最新の統計情報を作り直し、検索がスムーズに行えるように手助けします。
③ トランザクションIDの周回問題の防止
これは少し難しい話ですが、PostgreSQLには「データの鮮度」を管理するための番号札(トランザクションID)があります。この番号には上限があり、使い果たすとデータベースが止まってしまいます。VACUUMは古い番号札をリセットして、また最初から使えるように管理してくれます。これを専門用語で「凍結(フリーズ)」と呼び、システムの突然死を防ぐ大切な役割です。
4. 実践!VACUUMコマンドの使い方
実際にVACUUMを動かすための命令を見てみましょう。基本的には「自動バキューム(autovacuum)」という機能が勝手に掃除をしてくれますが、手動で行うこともできます。まずは一番シンプルな方法です。
VACUUM users;
この命令を出すと、指定した「users」という表の中にあるゴミを掃除して、再利用可能な状態にしてくれます。このとき、表全体をロック(他の人が使えないようにすること)しないので、サービスを止めずに実行できます。
次に、データを削除した後に掃除をする例を見てみましょう。例えば、佐藤花子さんが退会したとします。
DELETE FROM users
WHERE id = 2;
実行後のデータは以下のようになります。
id | name | age | email
---+----------+-----+-------------------
1 | 山田太郎 | 26 | taro@example.com
3 | 鈴木一郎 | 40 | ichiro@example.com
この状態でも、やはり「佐藤花子さんのデータがあった場所」はゴミとして残っています。ここでVACUUMを実行することで、その場所が再利用可能になります。
5. VACUUM FULLと通常VACUUMの違い
VACUUMには、さらに強力な「VACUUM FULL(バキューム・フル)」という命令があります。普通のVACUUMは「ゴミを空き地にするだけ」ですが、VACUUM FULLは「表全体を新しく作り直して、ファイルをぎゅっと圧縮する」という作業を行います。
例えるなら、普通のVACUUMは「部屋のゴミを拾ってゴミ箱に捨てる」程度ですが、VACUUM FULLは「家具を全部外に出して、床を磨き上げ、最小限のスペースに荷物を詰め直して引っ越しする」くらいの徹底的な掃除です。
注意点:VACUUM FULLの落とし穴
非常に強力で効果も高いですが、大きなデメリットがあります。それは、実行中にその表を「誰も触れなくなる」ことです。データを見ること(参照)すらできなくなります。また、処理に非常に長い時間がかかるため、本番で動いているサービスで不用意に実行すると、ウェブサイトが何時間も止まってしまうという大惨事になりかねません。普段は自動バキュームに任せ、どうしても必要な時だけ慎重に行う特別な手段です。
6. チューニングと自動バキュームの設定
「チューニング」とは、機械のネジを締めて最高の状態に調整することです。PostgreSQLでは、この掃除をどのくらいの頻度で行うかを細かく設定できます。これを「自動バキュームのチューニング」と呼びます。
例えば、「データが20%書き換わったら掃除を開始する」といったルールを決められます。ゴミが溜まりすぎる前に掃除をすれば、1回あたりの掃除時間は短くて済み、パソコンへの負担も抑えられます。初心者のうちは初期設定のままでも大丈夫ですが、データ量が増えてきたら、この掃除頻度を調整することが、エンジニアとしての第一歩になります。
7. 掃除をサボるとどうなる?インデックスと肥大化の関係
掃除を長期間忘れると、「テーブル肥大化(膨張)」という現象が起こります。本来100MB(メガバイト)で済むはずのデータが、ゴミのせいで1GB(ギガバイト)以上に膨れ上がってしまうことも珍しくありません。
さらに、データを探すための「索引(インデックス)」という辞書のような仕組みも、ゴミのせいでページ数が膨れ上がります。辞書が分厚くなれば、当然めくる手間が増え、検索スピードはガタ落ちします。データベースのパフォーマンスチューニングにおいて、VACUUMを適切に理解し、運用することは、どんな高度なプログラムを書くことよりも大切な基礎技術なのです。
-- インデックスも含めて全てのゴミを確認しながら掃除する
VACUUM ANALYZE;
上記のコマンドにある「ANALYZE」を付けると、掃除のついでにデータの分布(どのくらいの年齢層が多いか、など)を詳しく分析してくれます。これにより、司令塔はさらに賢くなり、データの検索がより一層高速化されます。これはまさに、データベースの「健康診断と大掃除」を同時に行っているようなものです。