2012-07-05 19 views
6

私はCassandra 1.1.2を使用しています。RDBMSアプリケーションをCassandraに変換しようとしています。Cassandra:より大きいまたはより小さい(< and >)を含むwhere節を使用したクエリ

| Col1 | Col2 | Col3 | Col4 | 
  1. のCol1::文字列(主キー)
  2. Col2に:文字列(主キー)
  3. COL3:BIGINT(インデックス)
  4. COL4私のRDBMSのアプリケーションでは、私はテーブルと呼ばれるTABLE1次ています:Bigint

この表には2億以上のレコードが含まれています。私は、テーブルを作成するには、次のステートメントを使用

カサンドラで
Select * from table where col3 < 100 and col3 > 50; 

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

create index on table1(col3); 

私は余分な列に主キーを変更する(私は自分のアプリケーション内のキーを計算する)主に使用されたクエリのようなものです。この結果は

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

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

クエリがtable1のどこからcol3という= 67点の作品COL1、COL2、COL3、COL4を選択私はCQL次のコマンドを実行しようとしたいくつかのレコードをインポートした後

Googleでは、この種のクエリを実行する方法はないと語っています。そうですか?どのようにそのようなクエリを作成するためのアドバイスですか?

答えて

6

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

お勧めのRandomPartitionerを使用してクラスターの周りをよく分散し、値に順次アクセスできる従来のバケット範囲パターンを使用することをお勧めします。この場合のアイデアは、第2の動的な列ファミリマッピング(バケツで順序付けされた)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に挿入するには、rangestart = int(col3val/1000000)と、indexotronに対応する行を挿入しなければなりません。次に、table1のすべての行をcol3> Xで列挙する必要がある場合は、indexotronの1000個のバケットをクエリする必要がありますが、その内のすべてのcol3valがソートされます。table1.col3 < 4021のためのすべてのtable1.primary_key値を検索する例クエリ:

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; 
+0

'select count(*)'も同様に便利かもしれませんが、FWIW ... – rogerdpack

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; 
... 

多分OKを使用しています。 (セカンダリインデックスでも同様の効果が得られますが、セカンダリインデックスは強く推奨されません)。理論的には "クライアント側のローカル"にも並列化できました。

「カサンドラのやり方」は「userid」のようなキーを持ち、それを「すべてのクエリ」の最初の部分として使用するので、データモデルを再考する必要があるかもしれません。 select * from table1 where userid='X' and col3val > 3であり、work(col3valのクラスタリングキーを想定)です。

関連する問題