Unix Architecture と Database Architecture との対比。
Unixが開発されていた頃と同じくらいに、リレーショナルデータモデルが提案されました。
SQLになった後、世界中を引き継いだ。多くのデータベースは実際にはUnixシステム上で動作します。 それらはまた、それらがUnixの哲学に従うことを意味しますか?
図4-9
ほとんどのデータベースシステムでのデータフローは、Unixツールとは大きく異なります。 通信チャネルとしてstdinとstdoutを使用するのではなく、データベースサーバがあります。 いくつかのクライアント(図4-9)。クライアントは、サーバー上のデータを読み書きするためのクエリを送信し、 サーバーは照会を処理し、クライアントに応答を送信します。この関係は基本的に 非対称:クライアントとサーバーは別個の役割です。
リレーショナルデータベースの設計理念もUnixとは非常に異なっています。 リレーショナルモデル(およびそれから派生したSQL)は、 システムの実装の詳細を隠すきれいな高レベルセマンティクスを定義します。 データベースがディスク上のデータをどのように表現するかに注意してください。
リレーショナルデータベースが何十年にもわたって大成功を収めたことは、これが成功した戦略であることを示しています。
一方、Unixの抽象度は非常に薄いです。単なる一貫した方法でハードウェアリソースをプログラムに提示しようとしています。それだけです。 小さなツールの構成はエレガントですが、SQLのようなものよりもはるかに低レベルのプログラミングモデルです。
この違いは、システムの拡張性に後続の影響を与えます。これまでUnixでは、処理パイプラインに任意のコードを追加することができました(図4-8)。 データベースでは、クライアントは通常、(アプリケーションコードなので)好きなことをすることができますが、 データベースサーバーの拡張性ははるかに限定されています(図4-10)。
図4-10
多くのデータベースは、独自のコードでデータベースサーバーを拡張するいくつかの方法を提供します。 たとえば、多くのリレーショナルデータベースを使用すると、ストアドプロシージャをPL/SQLなどの 独自のプロシージャ言語で記述できます(JavaScript8などの汎用プログラミング言語を使用できるものもあります)。 ただし、ストアドプロシージャで実行できることは限られています。 これにより、データベースのトランザクション保証を回避できなくなります。
いくつかのデータベースの他の拡張ポイントは、カスタムデータタイプ(これはPostgres9の初期の設計目標の1つ)、 外部データラッパー、およびプラガブルストレージエンジンのサポートです。 基本的にプラグインAPIです。特定の目的でモジュールがデータベースサーバーによって公開されているプラグインAPIに準拠していれば、 データベースサーバーでコードを実行できます。
この種の拡張性は、Unixツールで見た任意の合成可能性と同じではありません。 プラグインAPIは特定の目的のために提供されており、他の目的のために安全に使用することはできません。 プラグインAPIやストアドプロシージャで予期しない何らかの方法でデータベースを拡張したい場合は、 おそらくデータベースサーバーのコードを変更する必要があります。これは大きな仕事です。
ストアードプロシージャーは、保守や操作が難しいという評判もあります。 通常のアプリケーションコードと比較すると、監視、バージョニング、デプロイメント、デバッグ、 パフォーマンスへの影響の測定、マルチテナントリソースの分離などを処理することははるかに困難です。
データベースがオペレーティングシステムのようにはならない根本的な理由はなく、多くのユーザーが適切なセキュリティツールと 適切なセキュリティとアクセス制御を使用して、共有環境で任意のコードを実行してデータにアクセスすることができます。 しかし、データベースは過去数十年にわたって実際にこの方向に発展してこなかった。 データベースサーバーは、主にデータの格納と検索のビジネスの中にあり、任意のコードを実行させることが最優先事項ではありません。
しかし、なぜあなたはデータベースで任意の拡張性を必要としますか?足で自分を撮影するためのレシピではありませんか? さて、第2章で見たように、多くのアプリケーションではデータでさまざまなことを行う必要があり、SQLインターフェイスを備えた単一のデータベースでは不十分です。
図4-11
汎用データベースは、1つの製品(図4-11、「one size fits all」アプローチ)に多くの機能を提供しようとする可能性がありますが、 特定の目的に特化したツールと同様に機能しません実際には、さまざまな異なるデータストレージとインデックスシステムを組み合わせることで、 最良の結果を得ることができます。たとえば、同じデータをランダムアクセス用のリレーショナルデータベースに、 Elasticsearchでフルテキスト検索用に、分析のためにHadoopのカラム形式で格納され、memcachedの非正規化形式でキャッシュされます(図4-12)。
図4-12
さらに、カスタムコードを必要とするものもあり、既製のデータベースでは行えないものもあります。例えば:
•機械学習システム(特徴抽出、推薦エンジン、訓練された分類器など)は、通常、特定のアプリケーションに合わせてカスタマイズする必要があります。
•通知システムは、さまざまな外部プロバイダ(電子メール配信、SMS、モバイルデバイスへのプッシュ通知、ウェブフックなど)と統合する必要があります。
•キャッシュには、アプリケーション固有のビジネスロジックに応じてフィルタリング、集約、またはレンダリングされたデータが含まれている必要があります(複雑になる可能性があります)。
したがって、SQLとクエリプランナは大きな成果ですが、すべてのユースケースを満たすことはできません。 他のストレージシステムとの統合や任意のコードによる拡張性も必要です。 Unixはシンプルで構成可能なツールを使ってシステムを拡張性と柔軟性を持たせるエレガントな方法を提供してくれていますが、 データベースはUnixと似ていません。彼らはあなたが単一のプログラムで必要とするであろうすべての機能を実装しようとする、 非常に複雑でモノリシックな獣です。
図4-13
デフォルトでは、互換性のあるデータモデルを持っていても、あるデータベースを別のデータベースにパイプすることはできません(図4-13)。 バルクロードとバルクダンプ(バックアップ/スナップショット)は使用できますが、これらは一度限りの操作であり、 継続的に使用するようには設計されていません。チェンジ・データ・キャプチャ(第3章)では、これらのパイプのような統合を構築できますが、 CDCは多くのデータベースでは多少のフリンジ機能です。 主な入出力メカニズムとして変更ストリームを使用する主流のデータベースはわかりません。
また、サーバーがトリガーなどの拡張ポイントを提供していない限り、独自のコードをデータベースの内部処理パイプラインに挿入することもできません。
私はデータベースの設計が非常に自己中心的だと感じています。データベースは、それがあなたの宇宙の中心であると仮定しているようです: あなたがデータを保存して照会することができる唯一の場所、真実の源、すべての参照の宛先。
Unix上で見つけられるのと同じ種類の構成と拡張性はありません。 データベースによって提供される機能だけが必要な場合、この統合/モノリシックモデルは非常にうまく機能しますが、 1つのデータベースで提供できる機能以上のものが必要な場合は、機能が低下します。