3

Cassandra について 1 つのことがわかりません。たとえば、私は Facebook に似た Web サイトを持っており、人々は共有、いいね、コメント、画像のアップロードなどを行うことができます。

ここで、友達が行ったことをすべて取得したいとします。

  • Username1 さんがあなたのコメントを高く評価しました
  • username 2 さんがプロフィール写真を変更しました

等々。

user_likes user_commentsしたがって、多くのことを読んだ後、次のように、単一のものごとに新しい列ファミリーを作成する必要があると思いますuser_shares。基本的に、考えつくことは何でもできますが、それを行った後でも、データを検索できるようにするために、ほとんどの列のセカンダリ インデックスを作成する必要がありますか? それでも、どのユーザーが自分の友達であるかをどのように知ることができますか? 最初にすべての友人 ID を取得してから、各ユーザー ID についてすべての列ファミリーを検索する必要がありますか?

編集 わかりましたので、もう少し読んで、物事をもう少しよく理解しましたが、まだテーブルを構造化する方法を本当に理解できないので、賞金を設定し、どのように私の方法の明確な例を取得したいですかこの種の順序でデータを保存および取得する場合、テーブルは次のようになります。

  • 全て
  • いいね
  • コメント
  • お気に入り
  • ダウンロード
  • 株式
  • メッセージ

では、すべての友達またはフォローしている人の、最後にアップロードされた 10 個のファイルを取得したいとします。これは次のようになります。

John uploaded song AC/DC - Back in Black 10 mins ago

そして、コメントや共有のようなものはすべてそれに似ています...

おそらく最大の課題は、すべてのカテゴリの最後の 10 個のものを一緒に取得することです。したがって、リストはすべてのものの混合になります...

今、私は完全に詳細なテーブルでの答えは必要ありませんmysql.joins

4

3 に答える 3

5

SQL では、テーブルを構造化してデータを正規化し、インデックスと結合を使用してクエリを実行します。cassandra ではそれができないため、テーブルを構造化してクエリを処理しますが、これには非正規化が必要です。

友達がアップロードしたアイテムをクエリしたい場合、これを行う 1 つの方法は、ユーザーごとに 1 つのテーブルを持たず、そのユーザーの友達が何かをアップロードするたびにこのテーブルに書き込むことです。

friendUploads { #columm family
    userid { #column 
        timestamp-upload-id : null #key : no value
    }
 }

例として、

friendUploads {
    userA {
         12313-upload5 : null
         12512-upload6 : null
         13512-upload8 : null
    }
}

friendUploads {
    userB {
         11313-upload3 : null
         12512-upload6 : null
    }
}

アップロード 6 は 2 つの異なる列に複製されていることに注意してください。アップロード 6 を行った人は誰でもユーザー A とユーザー B の両方の友人であるためです。

ここで、フレンドのフレンド アップロード表示をクエリするには、userid 列で 10 の制限を指定して getSlice を実行します。これにより、キーでソートされた最初の 10 項目が返されます。

最新のアイテムを最初に配置するには、小さいタイムスタンプの前に大きいタイムスタンプを並べ替える逆コンパレータを使用します。

このコードの欠点は、ユーザー A が曲をアップロードするときに、friendUploads 列を更新するために N 回の書き込みを行う必要があることです。ここで、N はユーザー A の友達の数です。

各 timestamp-upload-id キーに関連付けられた値については、結果を表示するのに十分な情報を保存することも (おそらく json blob に)、何も保存せずに uploadid を使用してアップロード情報を取得することもできます。

書き込みの重複を避けるために、次のような構造を使用できます。

userUploads { #columm family
    userid { #column 
        timestamp-upload-id : null #key : no value
    }
 }

これは、特定のユーザーのアップロードを保存します。ユーザー B の友達のアップロードを表示したい場合、ユーザー B の友達ごとに 1 つずつ、N 回のクエリを実行し、アプリケーションで結果をマージする必要があります。これはクエリが遅くなりますが、書き込みは速くなります。

おそらく、ユーザーが何千人もの友達を持つことができる場合、最初のスキームを使用し、ユーザーのアップロード後にバックグラウンドで書き込みを実行できるため、クエリではなく書き込みを増やすことになりますが、クエリはユーザーがアップロードしている間に発生する必要があります。が待っています。

非正規化の例として、1 回のクリックが発生したときに twitter rainbird が行う書き込みの数を見てください。各書き込みは、1 つのクエリをサポートするために使用されます。

于 2012-10-14T18:54:48.830 に答える
1

いくつかの点で、noSQLをリレーショナルストアとして「扱う」ことができます。また、非正規化して処理を高速化することもできます。たとえば、PlayOrmの@OneToManyは、

user1 -> friend.user23, friend.user25, friend.user56, friend.user87

これはワイドローアプローチであるため、ユーザーを見つけると、彼の友人へのすべての外部キーがあります。各行の長さは異なる場合があります。また、逆参照を保存して、ユーザーが自分を友達としてマークした人への参照を持っているかもしれませんが、彼はそれらをマークバックしなかった(バディと呼びましょう)ので、

user1 -> friend.user23, friend.user25, buddy.user29, buddy.user37

正しく設計されていれば、データを「検索」する必要がない場合があることに注意してください。とはいえ、PlayOrmを使用すると、スケーラブルSQLと結合を実行できます(数兆行に拡張できるようにテーブルをパーティション化する方法を理解する必要があります)。

行には数百万の列を含めることも、10だけの列を含めることもできます。実際、今月はPlayOrmとnoSQLパターンの多くのドキュメントを更新しているところなので、これに注目すれば、さらに詳しく知ることができます。一般的なnoSQLについても同様です。

ディーン

于 2012-10-12T13:11:21.383 に答える
1

各 DB クエリは、別のマシンで実行されているサービスへの要求と考えてください。目標は、これらのリクエストの数を最小限に抑えることです (各リクエストにはネットワーク ラウンドトリップが必要なため)。

RDBMS パラダイムとの主な違いは次のとおりです。SQL では通常、結合とセカンダリ インデックスを使用します。関連するデータが異なるサーバーに存在するため、cassandra では結合できません。マテリアライズド ビューのようなものは、cassandra で同じ目的 (単一のクエリですべての関連データをフェッチする) で使用されます。

この記事を読むことをお勧めします: http://maxgrinev.com/2010/07/12/do-you-really-need-sql-to-do-it-all-in-cassandra/

twissandra サンプル プロジェクトを調べるにはhttps://github.com/twissandra/twissandra これは、あなたが説明した種類のプロジェクトの最適化テクニックの素晴らしいコレクションです。

于 2012-10-13T19:12:30.447 に答える