web-dev-qa-db-ja.com

MongoDBとPostgreSQLを一緒に使用する

私の現在のプロジェクトは、本質的には工場のドキュメント管理システムの実行です。

とはいえ、多少のしわ(驚き、驚き)があります。しわの一部はプロジェクトにかなり固有のものですが、一般的な答え(私はとにかく見つけることができません)がなく、より広い問題領域に適用できる一般的な観察と質問がいくつかあると思います。ここにはたくさんあり、StackExchangeのQ&A形式に適しているかどうかはわかりませんが、a)回答可能な質問であり、b)コミュニティに利益をもたらすほど具体的ではないと思います。私の考慮事項のいくつかは私に固有のものですが、SQLとNoSQLの両方を決定することに直面している誰にとっても、この質問は役に立ちそうだと思います。

背景:

私たちが作成しているWebアプリには、本質的にリレーショナルなデータとドキュメント指向のデータが含まれています。ケーキも食べてみたいです。

TL; DR:以下の#5はにおいテストに合格すると思います。あなたは?このようなSQLとNOSQLを単一のアプリケーションに統合した経験がある人はいますか?このクラスの問題に対して考えられるすべてのアプローチを以下にリストしてみました。有望な代替案を見逃しましたか?

複雑さ:

  • ドキュメントにはさまざまなクラスがあります。要件はすでに数十の異なるドキュメントを要求しています。この数は増加するだけです。最良のケースは、ドメインの専門家がDBAやプログラマーの介入なしに新しいドキュメントクラスの追加を処理できるように、単純なドメイン固有言語、コード生成、および柔軟なスキーマを活用できるケースです。 (注:私たちが住んでいることはすでに知っています グリーンスパンの第10の規則
  • 以前の成功した書き込みの整合性は、プロジェクトの中心的な要件です。データはビジネスに不可欠です。正常に書き込まれたものが書き込まれたままであれば、書き込みに関する完全なACIDセマンティクスを犠牲にすることができます。
  • ドキュメント自体は複雑です。特定のケースのプロトタイプドキュメントでは、ドキュメントインスタンスごとに150以上の個別のデータを保存する必要があります。病理学的なケースは桁違いに悪いかもしれませんが、確かに2つではありません。
  • 単一クラスのドキュメントは、後の時点で更新される可能性のある移動ターゲットです。
  • 私たちは、Djangoをリレーショナルデータベースにフックしたときに得られる無料のものを気に入っています。2つ前にジャンプしなくても、無料のものを保持したいと思いますDjango Django-nonrel forkを使用するバージョン1.3にダウングレードするよりも、ORMを完全にダンプする方が望ましいです。

基本的に、これはリレーショナルデータ(ユーザー、グループなどの一般的なWebアプリのもの、およびリアルタイムで複雑なクエリをスライスおよびダイシングできるようにする必要があるドキュメントメタデータ)とドキュメントデータ(例:結合やクエリに関心のない何百ものフィールド-データの唯一の使用例は、データが入力された単一のドキュメントを表示することです。

私は自分の優先する方法で健全性チェック(私の投稿履歴を確認した場合、私はDBAではないという事実についてかなり明白です)を行い、他の人が解決するために出くわしたすべてのオプションを列挙したかったリレーショナルデータと非リレーショナルデータの両方に関連する、ほぼ同様の問題。

提案されたソリューション:

1。ドキュメントクラスごとに1つのテーブル

各ドキュメントクラスは、すべてのメタデータとデータの列を持つ独自のテーブルを取得します。

利点:

  • 標準のSQLデータモデルが機能しています。
  • リレーショナルデータは可能な限り最良の方法で処理されます。必要に応じて、後で非正規化します。
  • Djangoのビルトイン管理インターフェースはこれらのテーブルの内省に慣れており、ORMはそのままの状態で100%のデータで快適に動作できます。

短所:

  • メンテナンスの悪夢。 (数十?)数千の列を持つ数十(数百?)のテーブル。
  • 書き込むテーブルを正確に決定するアプリケーションレベルのロジック。テーブル名をクエリのパラメーターにすると、臭いがします。
  • 基本的に、すべてのビジネスロジックの変更にはスキーマの変更が必要です。
  • 病理学的なケースでは、複数のテーブルにわたる単一のフォームのデータのストライピングが必要になる場合があります(参照: PostgreSQLテーブルの列の最大数は何ですか? )。
  • おそらく、人生と私たちを嫌うことになる間違いのない、真に正直な神のDBAを見つける必要があるでしょう。

2。 EAVモデリング

フィールドテーブルがあります。エンティティ属性値モデリングはすでに十分に理解されています。完全を期すために含めました。 2013年に開始される新しいプロジェクトは、意図的にEAVアプローチを採用するとは思いません。

利点:

  • 簡単にモデル化できます。

短所:

  • クエリがより困難です。
  • DBレイヤーは、1つのアプリレベルのオブジェクトを構成するものを簡単に表現できなくなりました。
  • DBレベルの制約チェックが失われます。
  • 1つのテーブルの行数は、数百倍から数千倍速く増加します。パフォーマンスに関して、将来の問題点と思われます。
  • 限定的なインデックス作成が可能です。
  • ORMに関する限り、DBスキーマは無意味です。バッテリーを含むWebアプリのものは保持されますが、カスタムデータモデルではカスタムクエリが必要になります。

3。 PostgreSQL hstoreまたはjsonフィールドを使用する

これらのフィールドタイプのいずれかが、リレーショナルDBのコンテキスト内でスキーマレスデータを格納するためのトリックを実行します。私がこのソリューションにすぐにジャンプしない唯一の理由は、それが比較的新しい(バージョン8.4で導入されたためではない新しい)ことです。疑わしい。 Mongoはドキュメント間の参照を処理できますが、ニースの簡単に正規化されたすべてのデータをMongoに投げ込むのと同じように感じるのとまったく同じ理由で、間違っていると思います。

利点:

  • Django ORMと組み込みの認証およびセッション管理の利点を利用できます。
  • 以前は他のプロジェクトで正常に使用していたすべてのものが1つのバックエンドに残ります。

短所:

  • 個人的には、これに関する経験はありません。
  • それは非常によく使われる機能のようには見えません。 NOSQLソリューションを検討している人々にかなり推奨されているようですが、それらが選択されているという証拠は多くありません。これは私が何かを逃しているに違いないと思います。
  • 格納されるすべての値は文字列です。 DBレベルの制約チェックを失います。
  • Hstore内のデータは、ユーザーが特にドキュメントを表示しない限りユーザーには表示されませんが、より標準的な列に格納されているメタデータは表示されます。私たちはメタデータを打ち負かし、私が作成するかなり大きなhstoreにはパフォーマンス上の欠点があるかもしれないと心配しています。

4。ドキュメント指向のフルボア

(MongoDBの意味で)すべてのものを文書化します。タイプDocumentの単一のコレクションを作成し、1日と呼びます。すべての周辺データ(ユーザーアカウント、グループなどのデータを含む)もmongoに取り込みます。このソリューションは明らかにEAVモデリングより優れていますが、同じ理由で#3が間違っているように感じます。どちらもハンマーをドライバーとして使用しているように感じます。

利点:

  • データを事前にモデル化する必要はありません。タイプDocumentのドキュメントを含むコレクションを1つ作成し、1日と呼びます。
  • コレクションが数百万または数十億ものドキュメントを網羅するまで拡大する必要がある場合、既知の優れたスケーリング特性。
  • JSON形式(BSON)は、開発者にとって直感的です。
  • 私がそれを理解しているように(現時点では漠然としているだけです)、書き込みの懸念レベルに関して偏執的であることにより、単一のインスタンスでさえ、ハードドライブがクラッシュするまでのすべての場合にかなり強力なデータ安全性を提供できます。

短所:

  • ORMはDjangoトランクのウィンドウの外にあります。認証フレームワーク、セッションフレームワーク、管理インターフェイスなど、他にも多くのものが含まれています。
  • Mongoの参照機能(複数のクエリが必要)を使用するか、データを非正規化する必要があります。 Djangoから取得した景品を失うだけでなく、PostgreSQLで当たり前と考えていたJOINのような景品も失います。
  • データの安全性。 MongoDBについて読むとき、それがどのようにしてデータを失うかについて言及している人が常に少なくとも一人いるようです。彼らは特定の出来事を引用することは決してなく、それはすべて大食いであるか、古いデフォルトの火災に関連しているだけかもしれません。もちろん、かなり偏執狂的なバックアップ戦略を利用します(データが静かに破損している場合、それはもちろん重要ではありません)。

5。 PostgreSQLおよびMongoDB

リレーショナルデータはリレーショナルデータベースに入り、ドキュメントデータはドキュメント指向データベースに入ります。リレーショナルデータベースのdocumentsテーブルには、インデックスを作成したりスライスしたりするのに必要なすべてのデータと、フィールドの実際の値をクエリする必要があるときに使用するMongoDB ObjectIdが含まれていますドキュメント。ドキュメント自体の値にORMまたは組み込みの管理者を使用することはできませんが、アプリ全体が基本的にドキュメントの管理者インターフェイスであるため、それほど大きな損失ではありません。 ORMの特定の部分を許容できない程度にカスタマイズして、必要な方法で機能させる。

利点:

  • 各バックエンドは、得意なことだけを行います。
  • 複数のクエリを必要とせずに、モデル間の参照が保持されます。
  • Djangoは、ユーザー、セッションなどに関する限り、私たちに提供してくれました。
  • 作成されるドキュメントのクラスの数に関係なく、documentsテーブルは1つだけ必要です。
  • クエリの頻度が低いドキュメントデータは、クエリの頻度がはるかに高いメタデータから強く分離されています。

短所:

  • ドキュメントデータを取得するには、最初にSQL DBに対して、次にMongoDBに対して2つの順次クエリが必要になります(これは、同じデータがMongoに格納されており、非正規化されていない場合と同じです)
  • 書き込みはアトミックではなくなります。単一のMongoドキュメントに対する書き込みはアトミックであることが保証されており、PGは明らかにアトミックな保証を行うことができますが、両方にまたがるアトミックな書き込みを保証するには、アプリケーションロジックが必要です。
  • 2つのバックエンド= 2つのクエリ言語=異なる管理要件を持つ2つの異なるプログラム=メモリを奪い合う2つのデータベース.
25
chucksmash

いくつかの考え....

通常、相互に密接に関連する情報を異なるシステムに保存することは望ましくありません。同期が外れる可能性は非常に高く、1つの問題ではなく2つの問題が発生します。 Mongoでできることの1つは、Mongoを使用してデータをパイプラインで送受信することです。私の好みは、可能な限りすべてをPostgreSQLに保持することです。ただし、これを行うにはPostgreSQLプログラミングの専門知識が本当に必要であり、高度な機能を使用することに専念したくないショップのためではないことに注意します。あなたとは少し異なるオプションのセットが表示されます。私の好みは私がリストされているものではないので、あなたにそれをあげます。

おそらく、メタデータを共通データ、クラスに必要なデータ、およびドキュメントデータに分離できます。この点で、基本的な共通情報とクラスごとに1つのテーブルを含む一般的なカタログテーブルがあります。このテーブルには、hstore、json、またはxmlフィールドがあり、これらのフィールドには、大幅に制約する必要のあるデータを格納する列とともに残りのデータが格納されます。これにより、クラスごとにこれらのテーブルに入力する必要のあるものが減りますが、制約を自由に活用できます。 3つのオプションには異なる問題があり、個別に検討する価値があります。

hstoreは比較的制限されていますが、多くの人が使用しています。それほど新しいものではありませんが、キーと値のストアであり、jsonやxmlとは異なり、データ構造をネストすることはできません。

jsonは非常に新しく、現時点ではあまり機能しません。これはそれで多くのことを行うことができないという意味ではありませんが、箱から出して多くをするつもりはありません。その場合、おそらくplv8jsで、または古い環境を使い続けたい場合は、plperluまたはplpythonで、かなりの量のプログラミングを行うことが期待できます。 jsonは、少なくとも現在の開発スナップショットではサポートされていますが、9.3ではより適切にサポートされているため、そのバージョンがリリースされると状況が改善されます。

xmlは、3つの中で最もサポートされており、ほとんどの機能と最も長いサポート履歴があります。次に、XMLです。

ただし、MongoとPostgreSQLを一緒に使用する場合は、PostgreSQLが2フェーズコミットをサポートしていることを意味します。つまり、書き込み操作を実行してからPREPARE TRANSACTIONを発行し、これが成功するとMongoでアトミックな書き込みを実行できます。それが成功した場合、PostgreSQLでCOMMITを実行できます。

14
Chris Travers

Presto または Dremio などのクエリエンジンを設定して、MongoDBとPostgresにあるデータを1つのクエリで結合できます。どちらもこれらのデータベースごとにコネクタがあり(ドキュメント here および here を参照)、それぞれ、「SQL on any」と「join Any」を実行することを提案します。

Prestoをテストするには、Hadoop、Hive、Prestoを使用してAWS EMRに小さなクラスターをデプロイできます(コマンドラインを使用しない場合は色相を追加します)。これはボックスから機能します。必ず これらに従ってください)コネクタのセットアップ手順 。 Hiveは必ずしも必要ではありませんが、MongoとPostgresの結合の結果を使用してテーブルを作成できます(例は このページ を確認してください)。 市場での有料バージョン もあります。これは(おそらく)大幅に最適化されており、30日間の試用版があります。

私はDremioを使用していませんが、AWS、Azure、またはオンプレミスでals それをデプロイするいくつかの簡単な方法 があります。彼らは ウェブサイトのいくつかのオンラインコース を利用して、クラスを無料でフォローできる「仮想ラボ」にアクセスできます。

0
kadu