web-dev-qa-db-ja.com

私の場合、MongoDBは正しい選択ですか?

Rails)で最初の実際のプロジェクトを構築します。これは、3つの主要な部分で構成されるWebアプリで構成されています。

  • データベースを使用しない静的部分
  • 各ユーザーの行は同じフィールドを持つため、データベースを必要とし、MySQLを使用できるユーザー登録部分
  • ユーザーがコレクション内のアイテムを作成、整理、編集し、他のユーザーと共有できる「アプリ」

いくつかのアイテムタイプがあり、それぞれに異なるオプションがあります。たとえば、次のオプションを持つ「ビデオ」アイテムがあるとします。

  • id
  • ユーザーID
  • collection_id
  • 題名
  • プラットフォーム(組み込みの場合)
  • uRL(埋め込まれている場合)
  • ファイル名(アプリでホストされている場合)
  • ファイルサイズ(アプリでホストされているID)

および「マップ」アイテム:

  • id
  • ユーザーID
  • collection_id
  • 題名
  • プラットフォーム(Googleマップ、Bingマップ...)
  • ロケーション
  • url
  • 地図サイズ

ユーザーがMySQLをアイテムに使用している間、各アイテムが別のアイテムとは異なるオプションを必要とする可能性があるため、MongoDBの柔軟性が役立つ場合があります。

これまで、私は常にPHPとMySQL(小さなプロジェクトでは常に共有ホスティングを使用))を使用しており、スケーラビリティはまったく新しいWordです。

学ぶ時間はありますが、1か月くらいで具体的なことができるようになりたいです。

私はMongoDBとNoSQLとRDMSとMySQLについてたくさん読んだので、それを試した後、MongoDBがどのように機能するかが好きだと言っておく必要があります。

  • 私の状況では、何をしますか?どうして?
  • スケーラビリティについて、MongoDBに問題がある可能性はありますか?はいの場合(DBサイズに関して)、これらの問題によりアプリが大幅に遅くなることがありますか?

編集:アプリの動作方法

多くの人がこれを私がアプリをどのように機能させたいかを尋ねたので:

  1. ユーザーがサインアップ
  2. 彼はログインしています
  3. 彼は無限のアイテムを作成できる彼の最初のコレクションisideを作成します
  4. アイテムにはさまざまなタイプがあり、タイプごとに異なるデータをデータベースに保存する必要があり、アイテムのタイプを追加または変更できます

ユーザーはその中に他のコレクションやアイテムを作成できます。

そのため、コレクションとその内部のアイテムのCRUDがあり、各コレクション/アイテムは特定のユーザーに参照されます

MySQLの主な問題は、スキーマが柔軟ではないことです。これを解決する方法があります(回避策?)?

NoSQLについて考えると、結合に関する疑問が1つだけあります。たとえば、コレクション内のid = user_idフィールドを持つユーザーに関連するデータを取得したい特定のコレクションがあるとします。

編集:MySQLを使い続けるという考え

「items」テーブルにフィールドを作成し、オプション設定を行います。各設定は|で区切られます。または別のシンボル。

次に、各アイテムのオプション設定の構造をどこかに保存します。たとえば、「ノート」アイテムタイプには、MySQLからデータを取得するときに、2つのオプション設定「color」と「strange_setting」が必要です。オプション設定のフィールドを配列の最初の項目が「色」用であることを認識する配列など。

どう思いますか?その解決策に問題がありますか?他にアイデアはありますか?

9

あなたがアプリで何をするつもりかをあなたが私たちに伝えるまで、私たちはあなたを助けることができないかもしれません。リレーショナルデータベースは特定の用途に適しており、NoSQLデータベースは他の用途に適しています。

誰かがかつてここで私に言ったように:

リレーショナルDBのリレーショナル部分は、他のいくつかの部分よりもはるかに最適化されています

これは、ユースケースに適合していると思われる場合にも、リレーショナルデータベースを使用できることを意味します。柔軟性/スケーラビリティーがあるため、MongoDBだけで進めないでください。これは、WikipediaのMongoDBに関する最初の行です。

MongoDB(「巨大」から)は、オープンソースのドキュメント指向のNoSQLデータベースシステムです。

本当にドキュメント指向のDBを使用するつもりですか?ユースケースにある程度のグラフ性がある場合は、グラフデータベースを使用することをお勧めしますNeo4jのように。または、SQLとNoSQLの両方のベストを一緒に使用することもできます。

ところで、私はSQLとNoSQLの両方の最良の部分を使用するプロジェクトもやっています。

編集:私はもう一度言います:

this の記事でNeo4jとHadoopのセクションをご覧ください。それは言う:

原則として、Hadoopおよびその他のKey-Valueストアは主に比較的フラットなデータ構造に関係しています。つまり、値、ドキュメント、オブジェクトなどの単純なオブジェクトの取得に関して、非常に高速でスケーラブルです。

同じ記事を参照して、MongoDBに使用するフラットなデータ構造が本当に必要ですか?これは最終的に、詳細な使用例、ステップ3と4がどのように実行されるかに依存します。

さらに、次の質問を参照することもできます。

https://stackoverflow.com/questions/2124274/mongodb-what-to-know-before-using

https://stackoverflow.com/questions/1476295/when-to-use-mongodb-or-other-document-oriented-database-systems

2番目の質問のトップ/選択された回答を確認してください。あなたはこれが単に解決するかもしれないそのジレンマにいます。

これらの質問には、知りたい情報がすべて含まれていると思います。結局のところ、それがMongoDbか他の何かであるかどうかを判断する必要があるのはあなたです。詳細なユースケースを知っているのは、あなたとあなたのチームだけです。

EDIT AGAIN(MySQL部分の場合):私が理解しているように、何かをdbに格納し、それらをセパレーターで区切ることを計画しています。これには2つの問題があります。

  1. セパレーターを持つ入力をさらに処理する必要があります。
  2. リレーショナルデータベースのリレーショナルストレージ部分は、文字列照合部分よりもはるかに最適化されています。特定の結果を取得するためにデータベースで文字列照合を行う必要があるスキームには行きません。もう一度強調します:

    リレーショナルDBのリレーショナル部分は、他の一部の部分よりもはるかに最適化されています(例:文字列マッチング)

  3. 複数値属性を使用しないでください。人々は一般にそれらを恐れます。
10
c0da

私はこの質問をよく見ます。それは常にどちらかとして考えられているようです。 MongoDBは素晴らしい新しいツールです。それは時々すべてのための光沢のあるツールのように見えることもあり、それは私の経験では不十分な選択になる可能性があります。

最良の組み合わせは間違いなく両方であると思います。ユーザーなどの一部にmylsqlを使用するアプローチを賞賛したいと思いますが、他の部分にはMongoDBを使用します。これは、認証と承認はmySQLで行うのが最善であり、これを非常にうまく行うたくさんの例とモジュール。

「多数のアイテム」の場合、ボリュームが高い場合、および/またはほとんどが読み取りである場合、および/または非構造化データである場合に、mongoDBの使用を検討します。

Mongoのスキーマレスな柔軟性に基づいて決定しないことをお勧めします。 SQLとsqlスキーマは、構造化されたデータを持ち、そのような構造でのみ可能な計算と変換を実行できる必要性から生まれました。これは、データウェアハウスの役割で5年間働いたことから学びました。パフォーマンスの問題については、MongoBDのみに注目します。大量のユーザーとリクエストがある、または予想している場合は、1秒あたり100,000ユーザーと20リクエストとすると、mongoDBを使用します。それ以外の場合は、SQLを使用します。多くの場合、私は少量用にmySQLを使用し、量、収入、インフラストラクチャがそれをサポートするように、mongoDBで混合する前にOracleに切り替えます。ボリュームの問題が発生する前に対処しないでください。ただし、どこに向かっているのかを明確に把握していて、途中で書き直したくない場合は、最初から適切なテクノロジーを選択してください。本当に大量の場合、スタックのすべてのレベルで使用するオプションとテクノロジーが膨大にあることに注意してください。

大まかに構造化されたデータには欠点があります。ここでは駐車場のアナロジーを使用します。入る最初の3台の車には分割線がありませんが、車が増えるにつれて、多くの混乱が起こり始め、駐車したり、簡単に車を数えたり、車線を空けたりしようとすると、悪夢になります。これを整理するには、事前に作業が必要です-ラインとディバイダー、トラフィックフローなどをマークアウトしますが、効果があります。もちろん時々物事が変化し(車が大きくなる)、あなたはいくつかの変更を行う必要があります-線を再描画します。加えて、毎年の再塗装とメンテナンスのための標準的なダウンタイムだけです。

スキーマ設計の側面は、おそらく伝統的なmysqlユーザーにとって最大のハードルになるでしょう。 スキーマ設計のMongoDbページ が役立つと思います。私の最後のポイントは、ミックスに追加するすべてのテクノロジーが複雑さを増すということです。多くの場合、あなたがそれを使用することを「持っている」と言う特定の作品には巨大な支持者がいますが、私は本当に大きな要因はちょうどそこにある作品の数です。これは、より多くの失敗の可能性がある点、および他の誰かがそれに取り組むために知る必要がある知識ベースのほとんどすべてを意味します。

fyi Rick Obsorneにはかなり驚くべき 比較図 非常にユニークです!

8
Michael Durrant

NoSQLとMySQLの有効な引数がたくさんあります。ただし、不足しているリンクの1つは規模に関するものです。本当に規模を拡大し、社内データベースでそれを実行したい場合は、データベースに関する多くの知識が必要になります。無限に拡大するシステムを実装しようとして失敗したホラーストーリーが多すぎます。

本当にNoSQLルートを使用することを選択した場合(そして、参加しないなど、それに伴うコストを受け入れる準備ができている場合)、AWS DynamoDB(http://aws.Amazon.com/dynamodb/)を検討してください。ここでは、データベース全体のスケーリング部分を忘れて、アプリケーションに集中できます。幸運を。

免責事項:私はAWS DynamoDBチームの開発者ですが、私たちは製品を本当に信じています。試してみてください:)

したがって、設計では2つの異なる種類のオブジェクトをデータベースに保存します。

  • ユーザーオブジェクト(常にフィールドを持つ)。
  • Appsオブジェクト(さまざまなフィールドを持つことができます)。アプリは1人のユーザーのみに属します。

コレクションは、さまざまなアプリをグループ化するための単なるタグであるように、別のオブジェクトとして作成することもできません。議論のために、コレクションはなく、ユーザーはアプリケーションのリストだけを持っているとしましょう。

MySQLでは達成できると思いますが、MongoDBではアプリオブジェクトの構造の点で柔軟性が高くなり、おそらくより自然に表現がデータベースにマッピングされるため、コードが単純になります。

MySQLでは、さまざまなアプリのさまざまな形式を処理するのに問題がありますが、それは可能です。いくつかのアイデア:

  • すべてのオブジェクト(id、user_id、titleなど)の間のすべての共通情報とタイプを使用して中間テーブルを作成できるので、そのフォーマットの非共通フィールドのみを含む別のテーブル(たとえば、 file_nameおよびfile_size(ファイルの場合)。フォーマットごとに異なるテーブルを作成する必要があります。両方のテーブルがapp_id(主キー)によってインデックス化されている場合、インデックス化された値によるテーブルへのアクセスが高速であるため、十分に高速です。
  • データを何らかの形式でエンコードし、標準化して保存できます。たとえば、JSONの非共通データを文字列としてエンコードし、VARCHARフィールドに格納します。領域が不足しないように、そのフィールドのサイズに注意してください。形式は、複雑(JSON)または単純(カンマで区切られた値のみ)にすることができます。
  • Int1、int2、str1、str2などのさまざまな「汎用」フィールドを作成し、アプリタイプのstr1が「file_name」であり、別のタイプの場合は「location」と定義できます。

MongoDBでは、2つのMongoDBコレクションを使用するのと同じくらい簡単で、1つはユーザー用、もう1つはアプリ用です。ある種の制限を想定すると(説明したとおりではありませんが、言っただけです)、アプリをユーザーオブジェクト内にリストとして格納することもできます。フィールドの種類に関係なく、あらゆる種類のオブジェクトを保存できるため、データの保存と取得がより自然になります。 user_idで検索して、ユーザーに属するすべてのアプリを取得できます。 MongoDBでは、とにかく結合クエリを実行する可能性を失いますが、この場合、基本的なクエリはユーザーを取得し、ユーザーに関連するアプリを取得することになると思います。 「3つ以下のアプリケーションで2つ以上のコレクションを持つユーザーに私に与える」などの多くのことを計画している場合は、結合クエリとしてではなく、コード内のプロセスとして生成する必要があります。リレーショナルデータベースよりも自然ではなくなり、処理に時間がかかる可能性があります。パラメータを検索する場合(たとえば、特定のユーザーに属するすべてのアプリを提供し、タイプXのすべてのアプリを提供します)、MongoDBでは非常に簡単で、結合を使用する必要はありません。

MongoDB on Railsのサポートについてはわかりません。 PythonおよびJavaScriptで使用しています。

編集:2つのテーブルと別のMySQLオプションにアクセスするときの時間に関するコメントを追加

1
Khelben

特に実際のプロジェクトであり、迅速にプッシュしたい場合は、最もよく知っているテクノロジーを使用すると思います。 MySQLとMongoを使用すると、どちらにも独自の利点と頭痛の種があります。両方で作業したので、優れた設計原則に従っている場合、MySQLからMongoに移行することはそれほど難しくありません。

そうは言っても、MongoDBを使用する理由の1つはデータです。あなたが述べたように、あなたはあなたのコレクションのためのいくつかの異なるタイプのエントリーがあります:マップ、ビデオなど。 RDBMSを使用してこれを実装する場合、3つの方法があります。

  • タイプごとのテーブル:各テーブルには、オブジェクトの各タイプに固有の列が含まれます

    欠点:すべてのデータ型を検索するNクエリ。

    利点:良いOO設計、保守が容易

  • 単一のテーブル:すべてのタイプのすべての可能な属性を含む1つの巨大なテーブル。ほとんどのエントリは特定のエントリに対してnullです。

    短所:オブジェクトを変更するにはテーブルを変更する必要があり、テーブルが大きくなると痛みを伴います。維持が難しい。

    利点:実装が簡単です。

  • メタデータを含むコアテーブル:タイトル、日付などのコア属性を含む単一のテーブルと、追加属性のキーと値のペアを含むメタデータテーブルがあります。

    欠点:1つのオブジェクトのすべてのデータを取得するための2つのクエリ。

    利点:非常に柔軟で、実装するのはそれほど難しくありません。

私はこれらのアプローチのそれぞれを以前に使用したことがあり、Mongoで作業するのは自然なことではありません。データはおそらく次のようになります。

{_id:"collection1",
 name:"My first Collection",
 owner: "user123243342",
 entries: [
    {type:"video",
     url: "http://www.youtube.com/234324",
     tags: ["roadtrip", "fun", "camera"]
     },
    {type:"map",
     coordinates: [LOC: [38, –102], LOC: [43, –33], LOC: [228, –102]],
     description: "Road trip to nowhere",
 ]
}

ただし、ドメインオブジェクトはそのまま永続化できるため、スキーマの設計について心配する必要はありません。 MongoDBは基本的に、クエリの対象となるオブジェクトストアです。

MySqlとMongodbのパフォーマンスの比較についての議論は省略していることに注意してください。常にパフォーマンスを念頭に置く必要がありますが、データアクセスパターンを知らないと、効果的に意思決定を行うことはできません。優れたプロジェクトは、成長して新しい課題が発生するにつれて、おそらくリファクタリングを数回繰り返します。時期尚早にパフォーマンスについて心配する必要はありません。最もよく知っているツールを選び、コーディングを開始してください。

編集

MySQLの使用および「|」を使用して同じフィールドに属性を保持することに関する特定の質問に回答する。これを行わないでください。このアプローチでは、解決する以上の問題が発生します。まず、MySqlを使用して個々の属性に対してクエリを実行することはできません。第2に、データアクセスレイヤーが非常に複雑になります。代わりに、type-per-tableまたはメタデータアプローチを使用してください。以前にWordPress=で作業したことがある場合は、メタデータアプローチを使用します。

  • ユーザーテーブル+ユーザーのusemeta
  • post table + postmeta table post

これにより、データ構造が非常に柔軟になり、妥当な速度でクエリを実行できます。

1
ltfishie

以下の記事は、データベース内のデータ量と取得されたデータ量を考慮して、選択、フェッチ、挿入に関してMySQLとMongoDBを比較した優れた結果を提供しています。結果は、「挿入」に関してMongoDBの優れたパフォーマンスを示していますが、他のケースではMySQLが勝っています。下記参照:

http://www.moredevs.ro/mysql-vs-mongodb-performance-benchmark/

MongoDBを使用した経験があり、良い解決策だと思います。毎日何千ものコレクションを挿入するために使用しました。 Solrソリューション(キャッシュソリューション、1日1回更新)と組み合わせると、必要に応じてコレクションIDでMongoDBデータを取得できるため、オンザフライで選択する必要はありません。したがって、多数の挿入を処理する必要があり、選択とフェッチを気にする必要がないことを考えると、MongoDBは優れたアイデアになる可能性があり、それはそれぞれのケースに依存し、適切な分析を行うことになります。

0
Rogerio Hilbert