PostgreSQLで最も嫌いな部分
- PostgreSQLはこの5年間、インターネットで最も愛されているDBMSとして定着してきた。これは、信頼性、機能性、拡張性、そして大半の運用ワークロードに適しているためである。
- しかし、PostgreSQLの多版同時実行制御(MVCC)の実装方式は、他のリレーショナルDBMSと比べて最悪だと評価されている。
多版同時実行制御とは?
- MVCCの目的は、複数のクエリが同時にデータベースを読み書きしても互いに干渉しないようにすることにある。
- DBMSは既存の行を上書きせずに複数のバージョンを保持し、クエリは要求を満たすために適切なバージョンを選択する。
- この方式により、明示的なレコードロックが不要になり、クエリはデータベースのスナップショットを観測できる。
PostgreSQLの多版同時実行制御
- PostgreSQLは既存の行を更新する際、新しいバージョンを生成して変更を適用する追記専用のバージョン保存方式を使っている。
- この方式は、さまざまな複雑な問題を引き起こす。
複数バージョンの保存
- PostgreSQLはすべての行バージョンを同じ保存領域に格納する。
- 更新時には新しいバージョンスロットを割り当て、既存バージョンをコピーして変更を適用する。
- PostgreSQLはバージョンチェーンを使って、バージョン間の関係を記録する。
バージョンのバキューム
- PostgreSQLは古いバージョンを削除するためにバキューム手順を使用する。
- 自動バキューム(autovacuum)は定期的に実行され、期限切れのバージョンを削除して領域を再利用する。
PostgreSQLのMVCCが最悪な理由
- PostgreSQLのMVCC実装は1980年代の設計に基づいており、現代のログ構造化システムのパターンと合っていない。
- PostgreSQLのMVCCで発生する4つの主要な問題を説明する。
問題1: バージョンのコピー
- PostgreSQLはすべての列を新しいバージョンへコピーするため、データの重複と保存容量の要求が増える。
- MySQLとOracleは差分を保存することで、この問題を回避している。
問題2: テーブル膨張
- PostgreSQLでは期限切れのバージョンが領域を占有し、自動バキュームがそれを削除できないとデータベースが成長し続ける。
- これはクエリ性能を低下させる。
問題3: セカンダリインデックスの保守
- PostgreSQLでは更新のたびにすべてのインデックスを更新しなければならない。
- これはクエリ性能を低下させる。
問題4: バキューム管理
- PostgreSQLの性能は、自動バキュームの有効性に大きく依存する。
- 自動バキュームが正しく機能しないと、性能問題が発生する。
GN⁺のまとめ
- PostgreSQLは今なお多くの支持を集めるDBMSだが、MVCCの実装方式は現代的ではない。
- PostgreSQLのMVCC問題を解決するには、多くの時間と労力が必要である。
- PostgreSQLの自動バキューム設定を最適化することで、性能を改善できる。
- PostgreSQLのMVCC問題に対する代替案として、MySQLとOracleを検討できる。
1件のコメント
Hacker Newsの意見
OrioleDB は新しいストレージエンジンでこの問題を解決しようとしていた
PostgreSQL の設計があらゆる面で悪いわけではない
Oracle と MySQL の MVCC 実装は、新しいバージョンの物理アドレスを保存しない
MySQL で単一行を更新する際は、SELECT id WHERE something; UPDATE what WHERE id=id のほうがずっと速い
2010年代には MongoDB が非永続的な書き込みのため "webscale" と見なされていた
pg_repackについての説明には同意しないVACUUM FULLは重いが、repack はより速く軽い代替手段であるPostgreSQL が人気を得た理由は次のとおり
PostgreSQL が新しい行タプルの完全な新規バージョンを保存するのは、基本ストレージエンジンの特性なのかという疑問がある
記事はよく書かれており、読みやすく理解しやすかった