TL;DR
- PostgreSQL Row Level Security(RLS)環境では、READ操作とCASCADE DELETE操作で最適なインデックス戦略が大きく異なる
- RLS複合インデックスでREAD性能は1.7倍向上、基本インデックスでDELETE性能は57倍向上
- マルチテナントSaaSアプリケーションでは用途に応じたインデックス設計が重要
検証背景
マルチテナントSaaSアプリケーションでは、PostgreSQLのRow Level Security(RLS)機能を活用してテナント間のデータ分離を実現することが一般的です。しかし、RLS環境下でのインデックス性能特性については詳細な検証データが少ないのが現状でした。
今回、実際のデータを用いて以下の2つのインデックス戦略を比較検証しました:
- 基本インデックス戦略(外部キー単一インデックス)
- RLS複合インデックス戦略
検証環境とデータ設計
テーブル構造
-- 企業テーブルCREATE TABLE companies ( id uuid PRIMARY KEY, name text NOT NULL);
-- 商品テーブルCREATE TABLE products ( id uuid PRIMARY KEY, company_id uuid REFERENCES companies(id) ON DELETE CASCADE, name text NOT NULL);
-- RLSポリシー設定CREATE POLICY "company_policy" ON productsUSING (company_id = current_setting('tenant.id')::uuid);
インデックス戦略比較
基本インデックス戦略:
CREATE INDEX idx_products_company_id ON products(company_id);
RLS複合インデックス戦略:
CREATE INDEX idx_products_company_product ON products(company_id, id);
性能測定結果
READ性能比較
インデックス戦略 | 実行時間 | 性能比 |
---|---|---|
RLS複合インデックス | 0.124ms | 1.7倍高速 |
基本インデックス | 0.214ms | ベースライン |
CASCADE DELETE性能比較
インデックス戦略 | 実行時間 | 性能比 |
---|---|---|
基本インデックス | 2.241ms | 57倍高速 |
RLS複合インデックス | 127.117ms | ベースライン |
技術的考察
READ性能が向上する理由
PostgreSQLのRLS機能は、クエリ実行時に自動的に暗黙的なフィルタを追加します。RLS複合インデックス(company_id, id)
は以下の利点があります:
- セキュリティフィルタリングとクエリ性能の両方を最適化
- インデックススキャンの効率性向上
- RLSポリシーによる暗黙フィルタとの親和性
DELETE性能が劣化する理由
外部キー制約のトリガーは、CASCADE DELETE実行時にRLSポリシーとは異なる動作をします:
- 複合インデックスはDELETE操作には過剰なオーバーヘッド
- 外部キー制約チェック時の効率性が低下
- 基本インデックスの方がシンプルで効率的
実践的な推奨事項
アプリケーション特性に応じた選択
READ中心のアプリケーション:
-- RLS複合インデックスを推奨CREATE INDEX idx_products_company_product ON products(company_id, id);
データライフサイクル管理重視:
-- 基本インデックスを推奨CREATE INDEX idx_products_company_id ON products(company_id);
ハイブリッドアプリケーション:
-- 複数インデックス戦略の検討CREATE INDEX idx_products_company_id ON products(company_id);CREATE INDEX idx_products_company_product ON products(company_id, id);
結論
PostgreSQL RLS環境では、READ操作とCASCADE DELETE操作で最適なインデックス戦略が大きく異なることが実証されました。
アプリケーションの主要な性能要件に基づいてインデックス戦略を選択することが重要です:
- READ重視: RLS複合インデックス戦略
- 削除処理重視: 基本インデックス戦略
- バランス重視: 複数インデックス戦略の検討
マルチテナント環境でのデータベース設計では、セキュリティ(RLS)と性能のバランスを慎重に検討し、実際のワークロードに基づいた検証が不可欠です。
補足
この記事はZennに投稿した記事のリライト版です。個人的に良い知見だったので、思考整理を兼ねて個人ブログにも残しておきます。