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

查询select col1,col2,col3,col4 from table1 where col3 = 67 works

谷歌表示没有办法执行这种查询。是对的吗?任何建议如何创建这样的查询?

4

2 回答 2

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中插入相应的行。那么当需要枚举col3>X中的所有行时,最多需要查询1000个桶,但是里面的s都会被排序。用于查找所有值的示例查询:indexotronrangestart = int(col3val / 1000000)table1indexotroncol3valtable1.primary_keytable1.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 回答