2

私は現在、すべてのシステムで公正な実装を実現するために、抽象的なデータ モデルと抽象的なクエリに基づいて SQL データベースと NoSQL データベースを比較するベンチマーク (これは私の学士論文の一部です) に取り組んでいます。

私は現在、次のように指定されたクエリの実装に取り​​組んでいます: 次のように指定された Cassandra のテーブルがあります。

CREATE TABLE allocated(
    partition_key int, 
    financial_institution varchar, 
    primary_uuid uuid,
    report_name varchar,
    view_name varchar,
    row_name varchar,
    col_name varchar,
    amount float,
PRIMARY KEY (partition_key, report_name, primary_uuid));

このテーブルには、約 100,000,000 レコード (~300GB) が含まれています。

report_nameview_namecol_name、およびrow_nameのすべての可能な組み合わせについて、フィールド「金額」の合計を計算する必要があります。

SQL では、これは非常に簡単です。合計 (金額) を選択し、必要なフィールドでグループ化するだけです。ただし、Cassandra はこれらの操作をサポートしていないため (まったく問題ありません)、別の方法でこれを実現する必要があります。

現在、私はこれを実現するために、テーブル全体のウォークを実行し、各レコードを処理し、組み合わせごとに Java の HashMap に合計を格納しています。私が使用する準備済みステートメントは次のとおりです。

SELECT 
   partition_key, 
   financial_institution,
   report_name, 
   view_name, 
   col_name, 
   row_name, 
   amount 
FROM allocated; 

これは、cassandra と Java アプリの両方で大量の RAM を搭載したマシンでは部分的に機能しますが、小規模なマシンではクラッシュします。

今、これをより速い方法で達成できるかどうか疑問に思っていますか? cassandra パーティション キーとしても機能する partition_key を使用して、すべてのパーティションに対してこれを行うことを想像できます (5 つ持っています)。

また、すべてのパーティションとレポートを個別のスレッドに割り当てて並列に実行することにより、これをマルチスレッド化することも考えました。しかし、これはアプリケーション側で多くのオーバーヘッドを引き起こすと思います。

実際の質問に移りましょう: これを達成するために別の実行戦略をお勧めしますか? たぶん、私はまだ SQL のように考えすぎているのかもしれません。

ご支援ありがとうございます。

4

1 に答える 1

3

ここにあなたを助けるかもしれない2つのアイデアがあります.

1) 次のアプローチを使用して、任意のテーブルの行を効率的にスキャンできます。PRIMARY KEY (pk、sk、tk) を持つテーブルを考えてみましょう。1000 のフェッチ サイズを使用しますが、他の値を試すこともできます。

最初のクエリ (Q1):

select whatever_columns from allocated limit 1000;

これらを処理し、主キーを形成する 3 つの列の値を記録します。これらの値が pk_val、sk_val、および tk_val であるとしましょう。次のクエリ (Q2) は次のとおりです。

select whatever_columns from allocated where token(pk) = token(pk_val) and sk = sk_val and tk > tk_val limit 1000;

上記のクエリは、同じ pk と sk のレコードを探しますが、tk の次の値を探します。1000 レコードを取得し続ける限り、繰り返し続けます。少ないものを取得すると、tk を無視し、sk でより多くのことを行います。これがクエリです(Q3):

select whatever_columns from allocated where token(pk) = token(pk_val) and sk > sk_val limit 1000;

繰り返しますが、1000 行を取得する限り、これを続けます。完了したら、次のクエリを実行します (Q4)。

select whatever_columns from allocated where token(pk) > token(pk_val) limit 1000;

ここで、最後のレコードの pk_val、sk_val、tk_val を再び使用し、これらの値で Q2 を実行し、次に Q3、Q4 の順に実行します.....

Q4 が 1000 未満になったら完了です。

2) 「report_name、view_name、col_name、row_name」は一意ではないと想定しているため、同じ組み合わせが再び表示されるたびに合計金額を追跡するためにハッシュマップを維持します。ここにもっとうまくいくかもしれないものがあります。キーがこれらの 4 つの値の組み合わせ (おそらく区切り) である cassandra でテーブルを作成します。3 つある場合は、これら 3 つの複合キーを単純に使用できます。ここで、リストである amount という列も必要です。割り当てテーブルを (上記のアプローチを使用して) スキャンしているときは、行ごとに次の操作を行います。

update amounts_table set amounts = amounts + whatever_amount where my_primary_key = four_col_values_delimited;

完了したら、このテーブルをスキャンして、表示された各行のリストの合計を計算し、必要な場所にダンプできます。キーは 1 つしかないため、token(primary_key) > token(last_value_of_primary_key) のみを使用してスキャンできることに注意してください。

私の説明がわかりにくい場合は申し訳ありません。これが役立つかどうか教えてください。

于 2014-01-19T07:47:13.860 に答える