2016-05-31 8 views
1

私は数億のレコードを持つ大規模なテーブルを持っています。このテーブルには、何百万というレコードに対して同じ値が繰り返されるフィールドを追加することを意味します。キャサンドラでこれを効率的にモデル化する方法はわかりません。私は手の込んだことを許可:cassandraの多くのレコードの繰り返し情報をモデル化する方法

私は、一般的なテーブルを持っている:

CREATE TABLE readings (
    key int, 
    key2 int, 
    time timestamp, 
    name text, 
    PRIMARY KEY ((key, key2) time) 
) 

この表は700.000.000+レコードを持っています。 sourceという名前のこのテーブルにフィールドを作成したいとします。このフィールドは、レコードがどこから入手されたかを示します(ソフトウェアには、readingテーブルの情報を受信する多くの方法があるため)。このフィールドの可能な値の1つは"XML: path\to\file.xml"または"Direct import from the X database"、さらには"Manually added"です。私はこのフィールドを説明的なフィールドにして、後で特定のソースからのレコードのみを操作するデータベースのメンテナンスを可能にするために使用します。

私は私が今していることができないことを実行したいクエリ:readingsテーブルに記録し

  • が与えられたソースから得たのですか?
  • 特定のレコードのソースは何ですか?私が最初にクエリを実行できるようにするだろうが、また、私は700.000.000+新しいレコードを作成することを意味します

    CREATE TABLE readings_per_source(
        source text, 
        key int, 
        key2 int, 
        time timestamp, 
        PRIMARY KEY (source, key, key2, time) 
    ) 
    

    :私のような表を作成するためのソリューションは以下のようになり

多くの情報を持つ私のデータベースでは、これらのレコードの何千万もがsourceの同じ値を持つので、不必要な記憶領域が多くなります。

これは、リレーショナル環境だった場合、私は唯一のreadingsテーブル上の行ごとに、追加の整数と新しいテーブルを保存する意味であろうと、readingsテーブルとid (PK)nameフィールドを持つsourceテーブルの上にsource_idフィールドを作成しますがさまざまな情報源と同じ数の記録がありました。

キャサンドラでこれをどのようにモデリングするのですか?

答えて

2

あなたのスキーマ

CREATE TABLE readings_per_source(
    source text, 
    key int, 
    key2 int, 
    time timestamp, 
    PRIMARY KEY (source, key, key2, time) 
) 

は非常に悪い考えです非常に非常に広いパーティションを持つ - あなたは、レコードの主キー(キー、KEY2)を使用してデータにアクセスする場合>ホットスポットあなた2番目のクエリのために

What is the source of a given record?は、それは非常に簡単です。 source列は、通常の列としてテーブルに追加することができます

最初のクエリの場合はWhich records on the readings table were gotten from a given source?はトリッキーです。ここでのアイデアは、同じソースを持つすべてのレコードを取得することです。

このクエリは、何千万ものレコードを返す可能性があることをご存知ですか

それはあなたが解決策があると、何をしたいなら、新しいSASIセカンダリインデックスを使用して(読んで私のすべての詳細についてblog post)と

CREATE TABLE readings (
    key int, 
    key2 int, 
    time timestamp, 
    name text, 
    source text, 
    PRIMARY KEY ((key, key2), time) 
) 

CREATE CUSTOM INDEX source_idx ON readings(source) 
USING 'org.apache.cassandra.index.sasi.SASIIndex' 
WITH OPTIONS = { 
    'mode': 'PREFIX', 
    'analyzer_class': 'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer', 
    'case_sensitive': 'false' 
}; 

その後、すべて取得するためにsource列に索引を作成します同じソースを持つレコードを使用するserver-side paging Javaドライバ(または他のDatastaxドライバ)の機能

+0

はい、私はクエリが多くのレコードを返す可能性があることを知っています、そして、目的のようです。問題になることはありますか?私は、単一のクエリで何百万ものレコードを返すことを意味します。また、私はある種のインデックスを作成することを考えていましたが、それを行う方法がわからなかったので、あなたの答えは大いに役立ちます。 1つの質問が残っています。単純に列を追加し、値を正規化されていない方法で繰り返すだけで、ストレージの過度の使用が発生しませんか? –

+0

また、私はpythonドライバを使用しています。ドライバが既に大きなクエリの結果を表示していることがわかりました。すでに行っていることとは異なる設定が必要ですか? –

+0

"しかし、1つの質問が残っています。列を追加して値を正規化されていない方法で繰り返すだけで、ストレージの過度の使用は発生しませんか?理論的には、実際には(デフォルトで)ディスク圧縮を有効にしておくと、スペースを節約するのに役立ちます。 – doanduyhai

1

http://www.datastax.com/2015/03/how-to-do-joins-in-apache-cassandra-and-datastax-enterpriseはカサンドラのテーブルに参加する方法についてはかなり良い記事です。

正規化されたデータは、関連するデータがテーブルを結合するために使用されるキーよりも大きい場合、常に正規化されていない(フラット)データよりも少ない記憶域を占有しますが、クエリ中に、

常にトレードオフがあります。完全に正規化されたデータの状態に関するトレードオフもあります。たとえば、住所を変更する顧客です。完全に正規化されたスキーマでは、アドレス変更が行われると、顧客、過去および現在のすべての請求書に新しい住所が表示されます。これは必ずしも望ましいことではありません。

多くの場合、請求書などの特定の時点でデータの状態を示すことが重要なレコードに履歴状態を提供するために、部分的に正規化することが望ましいです。この場合、請求書作成時に請求書に顧客住所データのコピーを保管します。

これは、価格設定や税金に関しても特に重要です。インボイスに保存されている価格/税金が必要なので、インボイスの作成時に顧客が支払った内容を表示することができます。そのため、請求書の価格は月額、製品の価格が変更されている可能性があります。それ以外の場合、あなたは会計悪夢を持っている!

スキーマを正規化/非正規化する方法を決定する際には、単純に記憶領域よりも多くのことを考慮する必要があります。 sourceは、パーティション・キーであり、あなたは、例えば同じソースを共有する数百万のレコードを持つことができるので、とりとめのため申し訳ありません

...

+0

実際にテーブルに参加する方法を見つけることは、私が望むものではなく、 sparkやODBC connなどの他のリソースectors。私の質問には少しの理論的な音があり、あなたの散歩は許されています。非常に有益な答え、私はそれを考慮に入れます。ありがとう! –

関連する問題