1. 導入
データベースのパフォーマンスを最適化する際、インデックスは強力な武器となりますが、むやみに増やせば良いというものではありません。使われていないインデックスは、データの更新(INSERT/UPDATE/DELETE)時に不要なオーバーヘッドを生じさせ、書き込み性能を低下させます。本記事では、PostgreSQLにおいて不要になったインデックスを安全かつ適切に削除するための手順と注意点を解説します。
2. 基礎知識
PostgreSQLにおけるインデックスは、テーブル内の特定の列に対して高速な検索を実現するためのデータ構造です。インデックスが存在すると、クエリはテーブル全体をスキャンすることなく目的のデータに到達できます。
しかし、その代償として「インデックスの更新」という処理が伴います。テーブルにデータを追加したり更新したりするたびに、関連するすべてのインデックスも書き換える必要があるため、不要なインデックスはシステム全体にとって「負債」となります。
3. 実装/解決策
インデックスを削除するには、SQLのDROP INDEXコマンドを使用します。基本的な書式は以下の通りです。
DROP INDEX [IF EXISTS] インデックス名 [CASCADE | RESTRICT];
IF EXISTSを付けることで、インデックスが存在しない場合にエラーになることを防げます。また、CASCADEを指定すると、そのインデックスに依存しているオブジェクト(もしあれば)も一緒に削除されます。基本的には意図しない削除を防ぐために、RESTRICT(デフォルト)を使用することを推奨します。
4. サンプルプログラム
以下に、インデックスを作成し、確認した上で安全に削除する一連のSQL操作を示します。
— 1. テスト用のテーブルを作成
CREATE TABLE users (id SERIAL PRIMARY KEY, email VARCHAR(255));
— 2. パフォーマンス向上のためにインデックスを作成
CREATE INDEX idx_users_email ON users (email);
— 3. インデックスの存在を確認(psql等のツールで実行)
— \di idx_users_email
— 4. 不要になったインデックスを安全に削除
— IF EXISTS を使うことで、削除済みの場合のエラーを回避します
DROP INDEX IF EXISTS idx_users_email;
— 5. 削除されたことを再確認
— \di idx_users_email
5. 応用・注意点
現場でインデックスを削除する際には、以下の点に注意してください。
・削除前に「使用状況」を確認する
PostgreSQLのシステムビュー「pg_stat_user_indexes」を確認することで、そのインデックスが実際に検索で使用されているか(idx_scanの値)を判断できます。長期間「idx_scan」が0、あるいは非常に少ないインデックスは削除候補です。
・ロックの問題
DROP INDEXはテーブルに対してアクセスクルーシブロック(排他ロック)を取得します。非常に大きなテーブルに対して実行すると、一時的に該当テーブルへのアクセスがブロックされる可能性があります。本番環境では、トラフィックの少ない時間帯に行うか、CONCURRENTLYの指定が可能か(PostgreSQLのバージョンや条件による)を事前に検討してください。
・運用環境での慎重さ
「本当に使われていないか」を判断するために、削除予定のインデックスを一時的に「無効化(pg_index.indisvalidをfalseにする)」する手法もありますが、基本的には運用監視期間を設けて、削除の影響を十分に調査してからDROP INDEXを実行するようにしましょう。

コメント