Java Cassandra中的范围查询
我正在使用Cassandra2.1.2和相应的DataStax Java驱动程序以及DataStax提供的对象映射 下表定义:Java Cassandra中的范围查询,java,cassandra,datastax-java-driver,Java,Cassandra,Datastax Java Driver,我正在使用Cassandra2.1.2和相应的DataStax Java驱动程序以及DataStax提供的对象映射 下表定义: CREATE TABLE IF NOT EXISTS ses.tim (id text PRIMARY KEY, start bigint, cid int); 映射: @Table(keyspace = "ses", name = "tim") class MyObj { @PartitionKey private String id; pr
CREATE TABLE IF NOT EXISTS ses.tim (id text PRIMARY KEY, start bigint, cid int);
映射:
@Table(keyspace = "ses", name = "tim")
class MyObj {
@PartitionKey
private String id;
private Long start;
private int cid;
}
访问者
@Accessor
interface MyAccessor {
@Query("SELECT * FROM ses.tim WHERE id = :iid")
MyObj get(@Param("iid") String id);
@Query(SELECT * FROM ses.tim WHERE start <= :sstart")
Result<MyObj> get(@Param("sstart") long start);
}
这似乎不起作用(我读了很多解释,为什么它决定不支持这一点,但我仍然不明白为什么有人会给出这样的限制,无论如何……)
所以,据我所知,WHERE子句中必须至少有一个等式
@Query(SELECT * FROM ses.tim WHERE cid = :ccid AND start <= :sstart")
CREATE INDEX IF NOT EXISTS myindex2 ON ses.tim (cid);
然后我试着
id text, start bigint, cid int, PRIMARY KEY (id, start, cid)
与
但还是没有运气
此外,我尝试将“start”设置为PartitionKey,但只能再次使用Equals进行查询
我错过了什么?如何获得此类查询的结果
编辑:版本更新为正确版本
我用的是卡桑德拉2.1.3
我不认为2.1.3已经发布。当前显示2.1.2为最高版本
从我所看到的情况来看,这里的主要问题是分区键id
要么是唯一的,要么基数太高,对您没有用处。目前,您正在采用RDBMS风格的方法(通过唯一ID)存储数据。使用Cassandra,您希望以查询数据的方式存储数据。第一步是选择一个好的键来对数据进行分区
因此,我尝试创建一个二级索引
在这里您不想做的另一件事是使用二级索引。我看得出你很想这么做,你应该马上把这个想法忘掉。二级索引是为了方便而创建的。它们不是为了性能而创建的,也不是为了在数据模型上采用快捷方式而创建的
Cannot execute this query as it might involve data filtering and thus
may have unpredictable performance.
说到临时性,当看到此消息时,您可能会考虑尝试向查询中添加ALLOW FILTERING
。绝对不要那样做。它直截了当地警告您这样做不会有好的表现,您应该注意这个警告
如果这能起作用,我必须知道cid的所有可能值,并分别查询它们,然后在客户机上执行其余的操作
cid的唯一性如何?如果必须获取并迭代所有的<代码> CID s太繁琐,那么您应该考虑选择/创建一个不太独特的值来进行分区。但是,假设cid
将起作用,表定义应该是这样的:
CREATE TABLE IF NOT EXISTS ses.tim
(cid int,
start bigint,
id text,
PRIMARY KEY ((cid),start);
@Table(keyspace = "ses", name = "tim")
class MyObj {
@PartitionKey
private int cid;
@ClusteringColumn(0)
private Long start;
private String id;
}
有了这个基础表定义,这个查询现在应该可以工作了
@Query("SELECT * FROM ses.tim WHERE cid = :ccid AND start <= :sstart")
<代码> >查询(从SESS.TIME中选择SED,CID=:CCID和Stest
)如果您对同一组数据有不同的查询能力需求,您可以考虑对数据进行反规范化。根据您的问题,听起来您想要如下:
- 按
id
- 通过
start
cid
上分区,因为您需要知道cid
的所有可能值
我能想到三个想法:
- 使用伪主键创建一个单独的表,以便将所有数据存储在同一分区中。但是,如果有多个条目创建超宽分区,并且在任何节点上保留该数据的热点,则可能会出现问题。您计划拥有多少个
然后可以进行如下查询:create table if not exists tim ( dummy int, start bigint, id text, cid int, primary key (dummy, start) );
select * from tim where dummy=0 and start <= 10;
从tim中选择*,其中dummy=0,并开始查看此工具以可视化数据模型(仍在开发中)。第三个选项卡将为您的表定义提供可能的查询:谢谢,我同意您的第一个建议,使虚拟PK具有一定的范围以避免hotspotting@divadpoc你可能误解了Andy的观点。他说用虚拟PK存储数据是“有问题的”,因为它会超宽分区和任何节点上的热点都保存该数据。“使用虚拟PK,您将遇到热点…更不用说无限行增长的问题了。@BryceAtNetwork23感谢您指出这一点。我没有误读它。我想看看它在有一个范围(而不仅仅是一个值)时的性能如何。”可能扩大范围…写“避免”热点是我的错…我只是想看看它是如何执行的,如果热点太糟糕,我们必须考虑其他的想法在这里指出。
@Query("SELECT * FROM ses.tim WHERE cid = :ccid AND start <= :sstart")
create table if not exists tim ( dummy int, start bigint, id text, cid int, primary key (dummy, start) );
select * from tim where dummy=0 and start <= 10;
select * from tim where start <= 10 ALLOW FILTERING;