7

次の特性を持つデータベースを構築しています。

  1. 行ごとに可変数の列を持つスキーマレス データベース。
  2. 数千万のレコードと数千の列。
  3. 1 日あたり数百万のクエリ。
  4. 1 日あたり数千の書き込み。
  5. クエリは、(キーだけでなく) 複数の列でフィルタリングされます。

ビルド トゥ スケールの Cassandra を検討しています。

私の質問は次のとおりです。

  1. この場合、水平方向にスケーリングする必要がありますか?
  2. Cassandra は、同じ列ファミリーを指す複数のキーを持つことをサポートしていますか?

編集

私はあなたの主張が正しいことを確認したいと思います。したがって、次の例は、あなたの答えから得たものを書き留めています。

したがって、次の列ファミリーがあるとします (いくつかのストア製品とその詳細を保持します)。

products // column-family name
{
x = {   "id":"x", // this is unique id for the row. 
    "name":"Laptop",
    "screen":"15 inch",
    "OS":"Windows"}
y = {   "id":"y", // this is unique id for the row. 
    "name":"Laptop",
    "screen":"17 inch"}
z = {   "id":"z", // this is unique id for the row. 
    "name":"Printer",
    "page per minute":"20 pages"}
}

そして、「名前」検索パラメーターを追加したいので、次のように異なる行キーを持つ CF の別のコピーを作成します。

products
{
"x:name:Laptop"  = {    "id":"x", 
            "name":"Laptop",
            "screen":"15 inch",
            "OS":"Windows"}
"y:name:Laptop"  = {    "id":"y", 
            "name":"Laptop",
            "screen":"17 inch"}
"z:name:Printer" = {    "id":"z", 
            "name":"Printer",
            "ppm":"20 pages"}
}

同様に、"screen" 検索パラメーターを追加するには、次のようにします。

products
{
"x:screen:15 inch" = {  "id":"x" 
            "name":"Laptop",
            "screen":"15 inch",
            "OS":"Windows"}
"y:screen:17 inch" = {  "id":"y", 
            "name":"Laptop",
            "screen":"17 inch"}
}

しかし、10 個の検索パラメーターまたはそれらの任意の組み合わせに基づいてクエリを作成する場合 (私のアプリケーションの場合のように)、列ファミリーの 1023 個のコピーを作成する必要があります [(2 の 10 乗)- 1]。そして、ほとんどの行には多くの検索パラメーターが含まれているため、(この方法で) データをモデル化するには約 1000 倍の追加ストレージが必要であることを意味します。これは、元の CF に 10,000,000 行ある場合は特に、少なくありません。

これはあなたが提案したデータモデルですか?


もう 1 つのポイント:セカンダリ インデックスを作成すると、スキーマレス モデルが失われたり、失われたりする理由を正確に理解することはできません。

4

1 に答える 1

3

Cassandra は、行キー以外でクエリできるデータベースではありません。ただし、これらのクエリをサポートするようにデータモデルを調整できます。

6 つの cassandra ノード クラスターで 1 日に 1 億 7,500 万件のクエリを実行します (簡単です!) が、データモデルをそのように動作させるため、row_keys と列を使用してデータを要求するだけです。インデックス付きクエリは使用しません。

より豊富なクエリをサポートするために、データを取得するためのキーを作成するための検索パラメーターとして使用するデータを使用して、データを非正規化します。

例:次のオブジェクトを保存するとします。

obj {
   id : xxx //assuming id is a unique id across the system
   p1 : value1
   p2 : value2
}

そして、これらのパラメーターのいずれかで検索したいことがわかっているので、次のように、column_names またはキーの obj のコピーを保存します。

"p1:value1:xxx"
"p2:value2:xxx"
"p1:value1:p2:value2:xxx" 
"xxx"

このようにして、p1 = value1、p2 =value2、p1 = value1 AND p2 = value2、または一意の ID xxx だけで obj を検索できます。

それをしたくない場合の唯一の他のオプションは、セカンダリインデックスとインデックス付きクエリを使用することですが、それは質問の「スキーマレス」要件を失います。



編集 - 例。

として定義されたオブジェクト「製品」を保存したい

class Products{
    string uid;
    string name;
    int screen_size; //in inches
    string os;
    string brand;
}

それを文字列または byteArray にシリアル化します (私は常に Jackson Json または Protobuf を使用する傾向があります...どちらも cassandra で非常にうまく機能し、超高速です)。そのバイト配列を列に入れます。

ここで重要なのは、列名と行キーを作成することです。画面の解像度で検索し、場合によってはブランドでフィルタリングしたいとしましょう。画面サイズのバケットを ["0_to15", "16_to_21", "21_up"] として定義します

指定された列:

"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}

1 つのコピーが保存されます: - key = "brand:Samsung" and column_name = "screen_size:15_uid:MI615FMDO548" - key = "brand:0_to_15" and column_name = "screen_size:15_uid:MI615FMDO548"

列名に uid を追加するのはなぜですか? 固有の製品に対してすべての列名を固有にするため。


例のパート 2では、追加したとしましょう

"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}"
"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"


最終的に、次の列ファミリーになります。

Products{
-Row:"brand:Samsung"
=> "screen_size:13_uid:MI615FMDO687":"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"
=> "screen_size:14_uid:MI615FMD5589":"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}
=> "screen_size:15_uid:MI615FMDO548":"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
=> "screen_size:17_uid:MI615FMD1111":"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
-Row:"screen_size:0_to_15"
=> "brand:Samsung_uid:MI615FMDO687":"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"
=> "brand:Samsung_uid:MI615FMD5589":"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}
=> "brand:Samsung_uid:MI615FMDO548":"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
-Row:"screen_size:16_to_17"
=> "brand:Samsung_uid:MI615FMD1111":"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
-Row:"uid:MI615FMDO687"
=> "product":"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"
-Row:"uid:MI615FMD5589"
=> "product":"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}
-Row:"uid:MI615FMDO548"
=> "product":"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
-Row:"uid:MI615FMD1111"
=> "product":"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
}

列名全体で範囲クエリを使用することで、ブランドや画面サイズで検索できるようになりました。



これが役に立ったことを願っています

于 2012-08-09T15:48:40.017 に答える