MongoDBとPostgreSQLを一緒に使用する


25

私の現在のプロジェクトは、基本的に工場文書管理システムの実行です。

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

背景:

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

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

複雑さ:

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

本質的には、リレーショナルデータ(ユーザー、グループなどの典型的なWebアプリのもの、および複雑なクエリをリアルタイムで切り刻むことができる必要があるドキュメントメタデータ)とドキュメントデータ(たとえば、参加やクエリに関心のない数百のフィールド-データの唯一のユースケースは、入力された単一のドキュメントを表示することです。

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

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

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

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

利点:

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

短所:

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

2. EAVモデリング

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

利点:

  • モデル化が簡単。

短所:

  • クエリがより困難です。
  • DBレイヤーには、1つのアプリレベルのオブジェクトを構成するものを簡単に表現することはなくなりました。
  • DBレベルの制約チェックが失われます。
  • 1つのテーブルの行数は、100〜1000倍の速度で増加します。おそらく将来の問題点はパフォーマンス面です。
  • 限られたインデックス付けが可能。
  • 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が間違っていると感じたのと同じ理由で、私には間違っていると感じています。

利点:

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

短所:

  • ORMはDjangoトランクの範囲外です。それと一緒にウィンドウを出て行く景品:authフレームワーク、セッションフレームワーク、管理インターフェイス、他の多くのもの。
  • mongoの参照機能(複数のクエリが必要)を使用するか、データを非正規化する必要があります。Djangoから得た景品を失うだけでなく、PostgreSQLで当たり前と思っていたJOINなどの景品も失います。
  • データの安全性。MongoDBについて読むと、データがどのように増えて失われるかについて、少なくとも1人の人が常に言及しているようです。彼らは特定の出来事を引用することは決してなく、それはただのホグウォッシュであるか、古いデフォルトの火災に関連しているだけで、書き込み懸念を忘れますが、それでも私を心配しています。もちろん、どのような場合でもかなり偏執的なバックアップ戦略を使用します(データが静かに破損した場合、それはもちろん重要ではありません。)

5. PostgreSQLおよびMongoDB

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

利点:

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

短所:

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

JSONデータ型の列に行きます。Postgresの新機能の使用を恐れないでください。Postgresチームは安定していない機能をリリースしません。そして、9.2は実際にはそれほど新しいものではありません)。さらに、9.3の新しいJSON機能を利用できるようになります。アプリケーションコード内のドキュメントを常に完全に処理している場合(SQLを使用するのではなく)、JSONを通常のtext列に格納することもできます。
a_horse_with_no_name

潜在的な回答者へ:気軽に回答してください!しかし、この質問は「完璧な」回答なしでかなり長く生き残ったので、実装して運用に移行したら、経験の完全な事後分析で質問に回答するつもりです。将来1年になるかもしれませんが、心配しないでください-OPが配信します。私はそれがこの特定の質問を気に入った/支持した人が最も有用だと思うことを期待しています:それが機能することの検証またはどの障害がサイドバイサイドオプションを殺したかの説明。
チャックスマッシュ

2
@chucksmash。結局のところ、5番で行きましたか?両方のデータベースをどのように実装しましたか?どのツールを使用しましたか?いいえの場合、なぜですか?
xpanta

@chucksmashまだあなたが約束したフィードバックを待っています。
バシットパリフ

@chucksmash OPは配信しませんでした... :(
アルバートロスマン

回答:


13

いくつかの考え....

通常、密接に関連する情報を異なるシステムに保存することは望ましくありません。物事が同期しなくなる可能性は非常に高く、手元に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でアトミックな書き込みを実行できます。それが成功したらCOMMIT、PostgreSQLでできます。


1
これらはすべて素晴らしい提案です。以前にhstore / jsonを使用することについて言及しました(xmlを黙って割引していましたが、それはxmlですから)。さらに、Postgres 2フェーズコミットの提案はゴールドです。私はこれが存在することを知りませんでした。素晴らしい提案をありがとう。
チャックスマッシュ

2段階のコミットは本当にゴールドです。これにより、NoSQLをタンデムで使用することが非常に実現可能になります。特に、2つのDB間のデータの相互関係がめったになく、それらが主に異なる問題を解決する場合
-haknick

0

PrestoDremioなどのクエリエンジンをセットアップして、MongoDBとPostgresにあるデータを単一のクエリで結合できます。どちらも、これらの各データベース用のコネクタが(ドキュメントを参照してください持っているここここ)と、それぞれ、「何でも上のSQL」と「何でも参加」を実行することを提案します。

(コマンドラインを使用したくない場合は、追加色相)プレストをテストするには、Hadoopの、ハイブとプレストでAWS EMR上の小さなクラスタを展開することができ、それが箱から作品-することを確認して設定するには、これらの指示に従ってくださいコネクター。Hiveは必ずしも必要ではありませんが、Hiveを使用すると、MongoとPostgres間の結合の結果を使用してテーブルを作成できます(例については、このページ参照してください)。マーケットプレイスには有料版もあり、これは(おそらく)大幅に最適化されており、30日間の試用版があります

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.