開発者のデータベース極端論の物語が、データストレージとビジネスロジックへの正しいアプローチについて激しい議論を巻き起こしている。この物語は、ストアドプロシージャの悪夢から同様に問題のあるキーバリューストアソリューションへのチームの軌跡を記録し、アーキテクチャの決定がスイートスポットを見つけることなく、いかに一つの極端から別の極端へと振れ得るかを浮き彫りにしている。
元の問題:暴走するストアドプロシージャ
レガシーシステムは、データベースの過度なエンジニアリングの典型的なケースに苦しんでいた。ビジネスロジックは完全にストアドプロシージャ内に存在し、複数の SQL Server データベースにまたがる複雑な結合を特徴としていた。これらのプロシージャはパフォーマンスのボトルネックとなり、有限のデータベースサーバーの CPU 時間を独占し、クエリプランが予期せず変更された際に予測不可能なレイテンシ問題を引き起こした。システムはまた、 MSDTC ( Microsoft Distributed Transaction Coordinator )に大きく依存しており、これが頻繁にデッドロックとシステム障害を引き起こしていた。
MSDTC:複数のデータベースやシステム間でトランザクションを調整する Microsoft のサービスだが、デッドロックや信頼性の問題を引き起こすことで悪名高い。
元のシステムの問題点:
- 複雑なストアドプロシージャに組み込まれたビジネスロジック
- 異なるサーバー間に分散された複数の SQL Server データベース
- MSDTC への過度な依存によるデッドロックの発生
- 予測不可能なクエリプランの変更によるタイムアウト
- VM 開発環境を必要とする15-30分のビルド時間
過度な修正:キーバリューストア極端主義
SQL の問題への対応として、アーキテクチャチームは正反対の方向への劇的な転換を行った。彼らはリレーショナルデータベースを完全に放棄し、読み取り、挿入、更新、単一キーの削除という4つの基本操作のみを提供するプリミティブなキーバリューストアを選択することを決定した。トランザクション、バッチ処理、複雑なクエリは一切許可されなかった。
このアプローチはほぼ即座に新たな問題を生み出した。高度にリレーショナルなビジネスデータは、時には数百キロバイトに達する大きな JSON ドキュメントに平坦化する必要があった。キーバリューストアにはドキュメントデータベースの機能が欠けていたため、小さな更新でさえドキュメント全体を読み取り、アプリケーションコードで変更を加え、その後すべてを書き戻す必要があった。チームは最終的にネットワークオーバーヘッドを削減するために圧縮を追加したが、これによりデータは標準的なデータベースツールでは検査不可能になった。
キーバリューストアの制限事項:
- 4つの操作のみ: 単一キーの読み取り、挿入、更新、削除
- トランザクションやバッチ処理のサポートなし
- 数百キロバイトに達する JSON ドキュメント
- 部分更新でも完全なドキュメントの読み取り/書き込みが必要
- Gzip 圧縮が必要で、標準ツールが使用不可
複雑性の爆発:チェックポイントシステム
データベーストランザクションがないため、チームはデータの整合性を処理するための精巧なチェックポイントシステムを構築した。すべての書き込み操作には UUID の生成とチェックポイントとしての保存、そしてリトライ中の重複操作を防ぐためにこの UUID をターゲットドキュメントに埋め込むことが必要だった。このアプローチは元のシステムと比較してデータベースラウンドトリップの数をほぼ倍増させ、レイテンシ問題を改善するのではなく悪化させた。
「実際には、以前5-10回のラウンドトリップを必要としていた同じデータベースへの書き込みが、追加のチェックポイント操作のためにほぼ倍の回数のトリップを必要とするようになった。」
チェックポイントシステムのオーバーヘッド:
- 全ての書き込み操作に対する UUID 生成
- 独立したシステムでのチェックポイント保存
- 対象ドキュメントへの UUID 埋め込み
- データベースのラウンドトリップがほぼ倍増(5-10回が約20回に)
- 冪等性のための複雑な再試行ロジック
コミュニティの視点:中間地点の議論
開発コミュニティはデータベースアーキテクチャの選択について深く分裂したままである。多くの開発者が、保守不可能なモンスターとなったストアドプロシージャについての恐怖体験を共有しており、ビジネスロジックが異なるデータベースシステムと言語に散らばっている。一方で、ストアドプロシージャには依然として存在意義があると主張する者もおり、特に大量データ操作や複数のアプリケーションが一貫したビジネスルールで同じデータベースにアクセスする必要がある場合においてである。
ORM 対生 SQL の議論も議論の中で強く浮上した。一部の開発者は ORM をパフォーマンスコストにもかかわらず時間を節約する生産性向上ツールと見なしているが、他の開発者は重要なデータベース最適化の機会を隠す抽象化と見なしている。コンセンサスは、単一のアプローチへの宗教的な固執がしばしば問題を引き起こすということのようである。
ORM:データベーステーブルとプログラミング言語オブジェクト間を変換する Object-Relational Mapping ツールで、データベース操作を容易にするが、時には効率性が劣る場合がある。
アーキテクチャバランスの教訓
この物語は、ソフトウェア開発における共通パターンを示している:一つの極端な問題を正反対の極端に振ることで解決しようとすることである。元のストアドプロシージャアプローチには正当な問題があったが、キーバリューソリューションは問題と共に数十年のデータベース最適化を投げ捨てた。より慎重なアプローチは、ストアドプロシージャのリファクタリング、インデックス戦略の改善、または慎重なパフォーマンス監視を伴う現代的な ORM の採用を含んでいたかもしれない。
この物語は、アーキテクチャの決定が過去の痛みポイントへの反応ではなく、具体的な技術要件に基づくべきであることを思い出させるものとして機能する。時として最良のソリューションは革命的な変化ではなく、既存システムの進化的改善にある。
参考: Wrong ways to use the databases, when the pendulum swung too far