(この記事の執筆時点での)すべての回答は、Redis、MongoDB、およびおそらくSQLベースのリレーショナルデータベースがそれぞれ本質的に同じツールである「データの保存」であると想定しています。彼らはデータモデルをまったく考慮していません。
MongoDB:複雑なデータ
MongoDBはドキュメントストアです。SQL駆動のリレーショナルデータベースと比較するには:リレーショナルデータベースは、インデックス化されたCSVファイルに単純化され、各ファイルはテーブルです。ドキュメントストアは、インデックス化されたJSONファイルに単純化されます。各ファイルはドキュメントであり、複数のファイルがグループ化されています。
JSONファイルの構造は、XMLやYAMLファイル、およびPythonのように辞書に似ているので、データをそのような階層で考えてください。インデックスを作成するときは、構造がキーになります。ドキュメントには名前付きのキーが含まれ、さらにドキュメント、配列、またはスカラー値が含まれます。以下のドキュメントを検討してください。
{
_id: 0x194f38dc491a,
Name: "John Smith",
PhoneNumber:
Home: "555 999-1234",
Work: "555 999-9876",
Mobile: "555 634-5789"
Accounts:
- "379-1111"
- "379-2574"
- "414-6731"
}
上記のドキュメントには、PhoneNumber.Mobile
値を持つキーがあります555 634-5789
。キーPhoneNumber.Mobile
が何らかの値を持つドキュメントのコレクションを検索できます。それらは索引付けされています。
また、Accounts
複数のインデックスを保持する配列もあります。文書を照会することが可能であるAccounts
含まれている正確に、値のいくつかのサブセットを、すべての値のいくつかのサブセットの、またはいずれかを値のいくつかのサブセット。つまりAccounts = ["379-1111", "379-2574"]
、上記を検索して見つけることはできません。Accounts includes ["379-1111"]
上記のドキュメントを検索して見つけることができます。Accounts includes any of ["974-3785","414-6731"]
上記を検索し、アカウント「974-3785」を含むドキュメントがあれば、それを検索できます。
ドキュメントは必要なだけ深く入ります。 PhoneNumber.Mobile
配列、またはサブドキュメント(PhoneNumber.Mobile.Work
およびPhoneNumber.Mobile.Personal
)さえ保持できます。データが高度に構造化されている場合、ドキュメントはリレーショナルデータベースからの大きなステップアップです。
データの大部分がフラットで、リレーショナルで、厳格に構造化されている場合は、リレーショナルデータベースの方が適しています。繰り返しになりますが、大きな兆候は、データモデルが相互に関連するCSVファイルのコレクションとXML / JSON / YAMLファイルのコレクションのどちらに最適であるかです。
ほとんどのプロジェクトでは、SQLまたはドキュメントストアが適合しない一部の小さな領域で、軽微な回避策を受け入れて、妥協する必要があります。広範囲のデータを格納するいくつかの大規模で複雑なプロジェクト(多くの列、行は無関係)の場合、一部のデータをあるモデルに格納し、他のデータを別のモデルに格納することは理にかなっています。FacebookはSQLとグラフデータベースの両方を使用します(データはノードに入れられ、ノードは他のノードに接続されます)。Craigslistは以前はMySQLとMongoDBを使用していましたが、完全にMongoDBに移行することを検討していました。これらは、データのスパンと関係が1つのモデルの下に置かれた場合、大きなハンディキャップに直面する場所です。
Redis:Key-Value
Redisは、基本的にはKey-Valueストアです。Redisでは、キーを指定して単一の値を検索できます。Redis自体は、文字列、リスト、ハッシュ、およびその他のいくつかのものを格納できます。ただし、名前でのみ検索します。
キャッシュの無効化は、コンピュータサイエンスの難しい問題の1つです。もう1つは、名前を付けることです。つまり、バックエンドへの何百もの過剰なルックアップを回避したい場合はRedisを使用しますが、新しいルックアップが必要な場合はそれを把握する必要があります。
無効化の最も明らかなケースは、書き込み時の更新です。を読み取ると、結果をとして保存user:Simon:lingots = NOTFOUND
できます。あなたはサイモン5 lingotsを授与する場合次に、あなたが読んで、と。これで、データベースとRedisに105があり、データベースにクエリを実行しなくても取得できます。SELECT Lingots FROM Store s INNER JOIN UserProfile u ON s.UserID = u.UserID WHERE u.Username = Simon
100
SET user:Simon:lingots = 100
user:Simon:lingots = 100
SET user:Simon:lingots = 105
UPDATE Store s INNER JOIN UserProfile u ON s.UserID = u.UserID SET s.Lingots = 105 WHERE u.Username = Simon
user:Simon:lingots
2番目のケースは、依存情報の更新です。ページのチャンクを生成し、それらの出力をキャッシュするとします。ヘッダーには、プレーヤーの経験、レベル、金額が表示されます。プレーヤーのプロフィールページには、統計情報を表示するブロックがあります。など。プレイヤーはある程度の経験を積む。さて、今あなたは、いくつか持っているtemplates:Header:Simon
、templates:StatsBox:Simon
、templates:GrowthGraph:Simon
などなどを、あなたがキャッシュされてきたところ、半ダースのデータベースクエリの出力は、テンプレートエンジンを介して実行フィールド。通常、これらのページを表示するときは、次のように言います。
$t = GetStringFromRedis("templates:StatsBox:" + $playerName);
if ($t == null) {
$t = BuildTemplate("StatsBox.tmpl",
GetStatsFromDatabase($playerName));
SetStringInRedis("Templates:StatsBox:" + $playerName, $t);
}
print $t;
の結果を更新したばかりなので、Key-ValueキャッシュGetStatsFromDatabase("Simon")
から削除templates:*:Simon
する必要があります。これらのテンプレートのいずれかをレンダリングしようとすると、アプリケーションはデータベース(PostgreSQL、MongoDB)からデータをフェッチしてテンプレートに挿入します。次に、結果をRedisに保存します。次回、その出力ブロックを表示するときに、データベースクエリを作成したり、テンプレートをレンダリングしたりする必要はありません。
Redisでは、パブリッシャーサブスクライブメッセージキューなども実行できます。それは完全に別のトピックです。ここでのポイントは、Redisはキーバリューキャッシュであり、リレーショナルデータベースやドキュメントストアとは異なります。
結論
ニーズに基づいてツールを選択してください。最大のニーズは通常、コードがどれほど複雑でエラーを起こしやすいかを決定するデータモデルです。専用のアプリケーションは、Cとアセンブリを組み合わせてすべてを書き込む場所であるパフォーマンスに依存します。ほとんどのアプリケーションは、一般化されたケースを処理し、RedisやMemcachedなどのキャッシュシステムを使用します。これは、高性能SQLデータベースやドキュメントストアよりもはるかに高速です。