私の場合、MongoDBは正しい選択ですか?[閉まっている]


9

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

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

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

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

「マップ」アイテム:

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

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

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

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

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

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

編集:アプリの仕組み

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

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

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

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

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

NoSQLについて考えるときの唯一の疑問は、結合に関するものです。たとえば、特定のコレクションがあり、コレクション内のID = user_idフィールドを持つユーザーに関連するデータを取得したい場合

編集:MySQLを使い続けるためのアイデア

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

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

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


4
技術的な推奨事項に関するマッテオの質問は、解決しようとしている特定の問題を提示しない限り、トピックから外れます。プロジェクトと、MySQL(使い慣れたデータベース)以外のデータベースを使用する必要があると思われる理由について、もう少し情報を提供する必要があります。例:スケーラビリティの懸念はありますか。また、新しいテクノロジーを調査するのにどのくらいの時間が必要ですか。質問を修正することを検討してください。修正する場合は、モデレートのためにフラグを付けて、編集内容を確認できるようにしてください。
yannis

回答:


10

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

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

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

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

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

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

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

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

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

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

同じ記事を参照して、MongoDBに使用するフラットなデータ構造が本当に必要ですか?これは最終的には、詳細なユースケース、ステップ3および4の実行方法によって異なります。

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

/programming/2124274/mongodb-what-to-know-before-using

/programming/1476295/when-to-use-mongodb-or-other-document-oriented-database-systems

2番目の質問の一番上/選択した答えを確認してください。これで解決するかもしれないジレンマに陥っています。

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

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

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

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

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

主に私はその柔軟なスキーマにMongoDBを使用するつもりでしたが、結合がないため、いくつかの疑問があります。とにかく、私のアプリでは、ユーザー用のdtabaseを用意してから、各要素がユーザーと要素のコレクションに関連付けられている基本的なcreudを作成します
Matteo Pagliazzi

mongoに参加する必要はありませんが、スキーマを計画する必要があります。mongoを使用する場合は、テーブルではなくオブジェクトについて考えてください。次に、オブジェクトにアクセスする方法を考えます。
ltfishie

8

私はこの質問をよく見ます。それは常にどちらかまたは両方として考えられているようです。MongoDBは素晴らしい新しいツールです。また、それは時々すべての光沢のあるツールのように見えるかもしれません、そしてそれは私の経験では悪い選択かもしれません。

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

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

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

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

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

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


それは私のレールでの最初の実際のプロジェクトです。それは趣味であり、今のところ、それが成功するか失敗するかはわかりませんが、ここでの最初の目的は、レールについて知ってトラフィックの話をすることができないようにすることです。読み取りはプライマリではなく、新しいデータと更新されたデータもたくさんあります...
Matteo Pagliazzi

1
mongodbの良い点は、スキーマが固定されていないことです。そのため、趣味のプロジェクトでは、設定作業が少なくなります。スキーマは時間の経過とともに変化する可能性があり、SQLテーブルを更新する追加の手順を実行する必要はありません。
ケビン

私の-1がわからない、または0の悪いアドバイスや反対の理由
Michael Durrant

とにかく、これがRailsの最初のプロジェクトである場合は、mySQLを使用します。レールで学ぶことがたくさんあります。カーテンを引き戻し始めてから1か月以上の価値があります。
Michael Durrant


3

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

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

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


1

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

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

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


MySQLを使用してオプションの設定を保存する2番目のオプションは、不要なバイトを多く含む各行をロードする可能性があるため、私は好きではありません... 2つの異なるテーブルから1つのアイテムをロードするには?
Matteo Pagliazzi

私の最後のアップデートを見てください
Matteo Pagliazzi

速度に関する質問については、それほど遅くなることはありません(インデックス付きの一意の値を介してアクセスしています)。最後に編集された提案は最初のアイデアに似ているため、私の回答も編集し、別のオプションを追加しました。
Khelben

1

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

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

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

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

    利点:優れたOO設計、維持が容易

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

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

    利点:実装が簡単です。

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

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

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

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

{_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
  • 投稿テーブル+投稿メタテーブル投稿

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


メタデータオプションが気に入らない...しかし、使用されていない場合にフィールドがnullのままになっている単一のテーブルについて考えている
Matteo Pagliazzi

シングルテーブルアプローチは、おそらく最悪の束です。単一のクエリですべてを実行できますが、単一のデータ型を変更すると、テーブルの変更が必要になります。そして、テーブルが大きくなると、mysqlの問題になります。
ltfishie 2012年

0

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

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

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

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