7

Cassandra 1.1.2 を使用しています RDBMS アプリケーションを Cassandra に変換しようとしています。私の RDBMS アプリケーションには、table1 という次のテーブルがあります。

| Col1 | Col2 | Col3 | Col4 |
  1. Col1: 文字列 (主キー)
  2. Col2: 文字列 (主キー)
  3. Col3: Bigint (インデックス)
  4. Col4: ビギント

このテーブルは 2 億件以上のレコードを数えます。主に使用されるクエリは次のようなものです。

Select * from table where col3 < 100 and col3 > 50;

Cassandra では、次のステートメントを使用してテーブルを作成しました。

create table table1 (primary_key varchar, col1 varchar, 
col2 varchar, col3 bigint, col4 bigint, primary key (primary_key));

create index on table1(col3);

主キーを追加の列に変更しました (アプリケーション内でキーを計算します)。いくつかのレコードをインポートした後、次のcqlを実行しようとしました:

select * from table1 where col3 < 100 and col3 > 50;

この結果は次のとおりです。

Bad Request: No indexed columns present in by-columns clause with Equal operator

クエリは、col3 = 67 が機能する table1 から col1、col2、col3、col4 を選択します

Google は、そのようなクエリを実行する方法はないと述べています。そうですか?そのようなクエリを作成する方法について何かアドバイスはありますか?

4

2 に答える 2

7

Cassandra インデックスは実際にはシーケンシャル アクセスをサポートしていません。それらがどこで役立つかについての簡単な説明については、http://www.datastax.com/docs/1.1/ddl/indexesを参照してください。しかし、絶望しないでください。Cassandra (および他の多くの NoSQL システム) を使用するより古典的な方法は、非正規化、非正規化、非正規化です。

あなたのケースでは、古典的なバケット範囲パターンを使用することをお勧めします。これにより、推奨される RandomPartitioner を使用して、クラスター全体に行を適切に分散させながら、値への順次アクセスを許可できます。この場合のアイデアは、2 番目の動的な columnfamily マッピング (バケット化および順序付けされた)col3値を関連する値に戻すことprimary_keyです。例として、col3値の範囲が 0 から 10^9 で、かなり均等に分散されている場合、それらをそれぞれ 10^6 の範囲の 1000 個のバケットに入れることができます (最適な粒度レベルは、必要なクエリの種類によって異なります)。 、持っているデータの種類、クエリのラウンドトリップ時間など)。cql3 のスキーマの例:

CREATE TABLE indexotron (
    rangestart int,
    col3val int,
    table1key varchar,
    PRIMARY KEY (rangestart, col3val, table1key)
);

に挿入するときtable1は、対応する行を に挿入する必要がありindexotronますrangestart = int(col3val / 1000000)table1次に、col3 > X ですべての行を列挙する必要がある場合、最大 1000 個の のバケットをクエリする必要がありますindexotronが、その中のすべての はcol3valソートされます。table1.primary_keyのすべての値を検索するクエリの例table1.col3 < 4021:

SELECT * FROM indexotron WHERE rangestart = 0 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 1000 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 2000 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 3000 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 4000 AND col3val < 4021 ORDER BY col3val;
于 2012-07-05T22:29:29.777 に答える
0

col3 が常に小さい値/範囲であることがわかっている場合は、元のテーブルにもマップする単純なテーブルを使用できる場合があります。例:

 create table table2 (col3val int, table1key varchar,
                      primary key (col3val, table1key));

と使用

 insert into table2 (col3val, table1key) values (55, 'foreign_key');
 insert into table2 (col3val, table1key) values (55, 'foreign_key3');
 select * from table2 where col3val = 51;
 select * from table2 where col3val = 52;
 ...

または

 select * from table2 where col3val  in (51, 52, ...);

範囲が大きすぎない場合は、おそらく問題ありません。(セカンダリ インデックスでも同じ効果が得られますが、セカンダリ インデックスはあまりお勧めできませんか?)。理論的には、「クライアント側でローカルに」並列化することもできます。

「Cassandraの方法」は「userid」のようなキーを持つことであり、それを「すべてのクエリ」の最初の部分として使用するため、データモデルを再考する必要があるかもしれませselect * from table1 where userid='X' and col3val > 3. (col3val にクラスタリング キーがあると仮定します)。

于 2018-02-12T21:34:14.417 に答える