2

Webサイトから一連の製品をスクレイピングし、それらをDBに保存しています。現在、私はMySQLを使用しており、次の2つのテーブルがあります。

products (product_id, site, product_description, etc)
    e.g. (1234, "xyz.com", "nice product", etc)
product_history (product_id, scrape_timestamp)
    e.g. (1234, 2012-01-02 10:53:09)
         (1234, 2012-01-03 11:02:09)

このスキーマは、過去にリストされた製品のスナップショットを取得できることを意味します。

NoSQLへの移行を検討しているのは、(i)さまざまなサイトからさまざまなフィールドを取得することが多く、(ii)データ量が年間約500万から1,000万の製品になるためです。スキーマを構造化する2つの方法を見ることができます

オプション1:「埋め込みリスト」

product_id,  site,      product_description, scrape_timestamp
1234,        "xyz.com", "test product",      {2012-01-02 10:53:09, 2012-01-03 11:02:09}

オプション2:「セカンダリインデックス」

keep both tables as above with the relational schema

オプション1はセカンダリインデックスが許可されているMongoDBのようなもので機能するのに対し、オプション2はMongoDBまたはDynamoDBのいずれかで機能すると思います。(メンテナンスのオーバーヘッドがゼロのクラウドでホストされるものが必要なため、これら2つを検討しています)。

私はこれらのアプローチで正しい方向に進んでいますか?どちらが最適ですか?私はnosqlにまったく慣れていないので、アドバイスをいただければ幸いです。

4

1 に答える 1

2

次のデータストレージの問題を解決しようとしていると言います。

  1. 年間約1,000万件の履歴データポイント
  2. 異種データポイント

年間約1,000万件の履歴データポイント

コメントに示されているように、年間1,000万データポイントはビッグデータセットではありません。MySQLを含むほとんどのデータベースは、それらを調整する方法を知っている限り、これをサポートできるため、この問題を解決するためだけにテクノロジーを切り替えないでください。MySQLの調整方法について具体的な質問がある場合は、別の質問を投稿することをお勧めします。

履歴データの問題に対するMongoDBベースのソリューションに関しては、おそらくproduct_historyデータのコレクションがあり、各ドキュメントに入れるエントリの数を決定するだけです。いくつかのオプション:製品ごとに1つ。製品/タイムスタンプごとに1つ。特定の期間内の製品/タイムスタンプごとに1つ。1日または1か月。さらにいくつかの詳細:

  • mongoのドキュメントによると、データを配列に埋め込むことは「特定のユースケースでは」意味があります。あなたのユースケースのように聞こえます。つまり、製品/タイムスタンプごとに1つのドキュメントを作成することはありません。
  • また、mongoは非常に長い配列の拡張があまり得意ではないため、製品ごとに1つのドキュメントは必要ありません。
  • したがって、残りのオプションは、特定の期間内の製品/タイムスタンプごとに1つです。これで行きなさい。残念ながら、このドキュメントの構成方法を正確に判断するには、いくつかのことを試す必要があります。試すべきことがいくつかあります:
    • 「期間」属性を使用して、問題の期間の開始時刻を示します。製品/期間のインデックスを作成します。
    • このドキュメント内のデータ構造に追加する場合、mongoのアップサート機能を使用してコードを簡略化できます。
    • 新しいデータポイントが着信する頻度に基づいて、期間(時間、日、月など)を選択します。おそらく、負荷テストに基づいてこの期間を調整する必要があります。
    • 期間ごとにドキュメントを構造化する最も簡単な方法は、1つの配列を使用してデータを保持することです。ただし、mongoは非常に長い配列に追加するのが得意ではないため、ドキュメント内に単純なツリーを作成することでパフォーマンスを向上させた人もいます。たとえば、日次ドキュメントがある場合は、その日の1時間ごとに個別の配列を使用できます。
{
  "0" : [ 123, 456 ],
  "1" : [ 789 ]
}

1台のサーバーのメモリに収まらない大量のデータがあり、履歴データを非常に迅速に読み取る必要がある場合は、MongoDBのシャーディングのサポートからいくつかのメリットを得ることができます。基本的に、読み取りがディスクにヒットする必要がないようにデータを分割することができます。ただし、読み取りのパフォーマンスが重要かどうか、どのような種類の読み取りを行うかは質問からは不明です。詳細が必要な場合は、新しい質問を投稿してください。

異種データポイント

あなたの問題に対するRDBMSソリューションに関して、私が見た中で最も一般的なアプローチは次のとおりです。

  • データを非正規化します。あなたはあなたが製品ごとに85の属性を持っていると言いますか?次に、85列のテーブルを作成します。別の製品には20の異なる属性があるとあなたは言いますか?次に、テーブルにさらに20列を追加します。このソリューション:
    • シンプルです。
    • 非正規化の通常の利点がすべて適用されるため、パフォーマンスは良好です。
    • リレーショナルデータベースを使用する利点のいくつかを損ないます。たとえば、ほとんどの列に「非ヌル」制約を設定することはできません。
  • データを正規化します。タイプXの属性をキャプチャするための1つのテーブル、タイプYの属性をキャプチャするための別のテーブルなどを作成します。新しい製品タイプがある場合は、新しいテーブルを追加します。このソリューション:
    • 複雑になる可能性があります。たとえば、特定の共通属性を配置するテーブルをどのように決定しますか?
    • パフォーマンスが悪い可能性があります。たとえば、データベースから有用な情報を取得するために10個のテーブルを結合する必要がある場合、問題が発生します。
    • データベースの純粋主義者を幸せにするでしょう。
  • 列の代わりに行を使用します。このソリューション:
    • 複雑でメンテナンスが難しい。
    • パフォーマンスが悪い。
    • リレーショナルデータベースを使用する利点のいくつかを損ないます。

(他にもRDBMSベースのソリューションがあることに注意してください。たとえば、XMLドキュメントをDB2に入れるのが好きな人もいます。)

あなたは最後のアプローチを試みているので、あなたが不幸であることは不思議ではありません!RDBMSを使い続ける場合は、リストした他のアプローチの1つに切り替えることをお勧めします。

では、NoSQLについての質問に戻りましょう。MongoDBなどのドキュメントベースのNoSQLデータベースは、スキーマがないため、「異種データポイント」の問題に対する魅力的なソリューションです。製品の仕様を1つのドキュメントにリストすることができます。新しい属性を追加する場合は、そうするだけです。MongoDBでは属性にインデックスを付けることができるため、属性Aの製品を検索する場合は、インデックスを使用してすばやく検索できます。(ただし、ここには魔法はありません。他のデータベースと同様に、インデックスの保守にはコストがかかる可能性があるため、慎重に作成してください)。

于 2012-02-14T20:36:29.063 に答える