4 ポイント 投稿者 GN⁺ 2024-10-21 | 1件のコメント | WhatsAppで共有

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件のコメント

 
GN⁺ 2024-10-21
Hacker Newsの意見
  • OrioleDB は新しいストレージエンジンでこの問題を解決しようとしていた

    • INSERT 処理が中心であれば、追加スペースは不要
    • トランザクション内の文数には制限があるが、COPY FROM を使えば回避できる
    • DBA の観点では、ロールバック/UNDO 用の領域を別途管理する必要がない
  • PostgreSQL の設計があらゆる面で悪いわけではない

    • MySQL と Oracle は新しいバージョンと現在のバージョンの間の圧縮デルタを保存する
    • git は diff を保存せず、PostgreSQL と似た形でオブジェクト全体を保存する
  • Oracle と MySQL の MVCC 実装は、新しいバージョンの物理アドレスを保存しない

    • その代わり論理識別子を保存し、DBMS が現在バージョンの物理アドレスを見つける
    • このため補助インデックスの読み取りは遅くなる可能性があるが、別の利点によってオーバーヘッドを減らしている
  • MySQL で単一行を更新する際は、SELECT id WHERE something; UPDATE what WHERE id=id のほうがずっと速い

    • 一般的な処理ではこの方法は使われず、そのため単発の DML が遅くなる
  • 2010年代には MongoDB が非永続的な書き込みのため "webscale" と見なされていた

    • これはマーケティングの結果だった
  • pg_repack についての説明には同意しない

    • VACUUM FULL は重いが、repack はより速く軽い代替手段である
  • PostgreSQL が人気を得た理由は次のとおり

    • データ安全性、ACID、Oracle との類似性、MVCC、SQL 標準準拠、Postgres チーム、コミュニティ、データ型、高い性能、BSD の柔軟性
    • PostgreSQL は継続的に進化しており、コミュニティが大きな役割を果たしている
  • PostgreSQL が新しい行タプルの完全な新規バージョンを保存するのは、基本ストレージエンジンの特性なのかという疑問がある

  • 記事はよく書かれており、読みやすく理解しやすかった

    • vacuum 関連の問題を理解する助けになり、図も良かった