Cassandra:使用where子句查询包含更大或更小的(<和>)

时间:2012-07-05 15:58:27

标签: cassandra where-clause cql

我正在使用Cassandra 1.1.2我正在尝试将RDBMS应用程序转换为Cassandra。在我的RDBMS应用程序中,我有一个名为table1的表:

| Col1 | Col2 | Col3 | Col4 |
  1. Col1:String(主键)
  2. Col2:String(主键)
  3. Col3:Bigint(索引)
  4. Col4:Bigint
  5. 此表包含超过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
    

    查询从table1选择col1,col2,col3,col4,其中col3 = 67

    Google表示无法执行此类查询。是对的吗?有关如何创建此类查询的任何建议吗?

2 个答案:

答案 0 :(得分:7)

Cassandra索引实际上并不支持顺序访问;请参阅http://www.datastax.com/docs/1.1/ddl/indexes,以便快速解释它们的用途。但不要绝望;使用Cassandra(以及许多其他NoSQL系统)的更经典的方法是非规范化,非规范化,非规范化。

在您的情况下,可能是一个好主意,可以使用经典的桶范围模式,它允许您使用推荐的RandomPartitioner并保持您的行在群集中良好分布,同时仍然允许顺序访问你的价值观。在这种情况下的想法是,您将第二个动态列家庭映射(分段和有序)col3值返回到相关的primary_key值。例如,如果您的col3值的范围从0到10 ^ 9并且分布相当均匀,您可能希望将它们放在1000个桶中,每个桶的范围为10 ^ 6(最佳粒度级别取决于您需要的一些查询,您拥有的数据类型,查询往返时间等。 cql3的示例模式:

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

插入table1时,您应在indexotron中插入相应的行,rangestart = int(col3val / 1000000)。然后,当您需要使用col3&gt;枚举table1中的所有行时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;

答案 1 :(得分: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, ...);

如果没有太大的范围,也许可以。 (您也可以使用辅助索引获得相同的效果,但不强烈建议使用辅助索引?)。从理论上讲,parallelize它也可以“在客户端本地”。

似乎“Cassandra方式”是拥有一些像“userid”这样的键,你将它用作“所有查询”的第一部分,这样你可能需要重新考虑你的数据模型,然后你可以查询{ {1}}它可以work(假设col3val上有一个聚类键)。