Ore*_*ren 8 indexing cassandra
EDIT1:在原始问题之后添加了一个描述问题的案例.
我想查询一个不属于我的密钥的列.如果我理解正确,我需要在该列上定义二级索引.但是,我希望使用大于条件(不仅仅是平等条件),而且似乎仍然没有支持.
我错过了什么吗?你会如何解决这个问题?
我想要的设置:
Cassandra 1.1.6
CQL3
CREATE TABLE Table1(
KeyA int,
KeyB int,
ValueA int,
PRIMARY KEY (KeyA, KeyB)
);
CREATE INDEX ON Table1 (ValueA);
SELECT * FROM Table1 WHERE ValueA > 3000;
Run Code Online (Sandbox Code Playgroud)
由于在Cassandra 1.1.6中仍然不支持在具有复合键的ColumnFamilies上定义二级索引,因此我必须解决丢弃其中一个键的临时解决方案,但我仍然遇到与非相等条件相同的问题.
还有另一种解决方法吗?
感谢您的时间.
相关来源:http : //cassandra.apache.org/doc/cql3/CQL.html#selectStmt http://www.datastax.com/docs/1.1/ddl/indexes
EDIT1
这是一个可以解释问题的案例.正如rs-atl所指出的那样,它可能是一个数据模型问题.假设我在stackoverflow上保留了所有用户的列族.对于每个用户,我保留了一批统计信息(Reputation,NumOfAnswers,NumOfVotes ......所有这些都是int).我想查询这些统计信息以获取相关用户.
CREATE TABLE UserStats(
UserID int,
Reputation int,
NumOfAnswers int,
.
.
.
A lot of stats...
.
.
.
NumOfVotes int,
PRIMARY KEY (UserID)
);
Run Code Online (Sandbox Code Playgroud)
现在我有兴趣根据这些统计数据切割UserID.我希望所有用户拥有超过10K的声誉,我希望所有用户的答案少于5,等等.
我希望有所帮助.再次感谢.
kee*_*lar 10
在CQL中,WHERE一旦为它们创建了索引(即二级索引),就可以在所有列上应用该子句.否则,您将收到以下错误:
Bad Request: No indexed columns present in by-columns clause with Equal operator
Run Code Online (Sandbox Code Playgroud)
不幸的是,即使使用辅助索引,由于性能问题,WHERE子句也需要通过CQL在辅助索引上至少有一个EQ .
问:为什么有必要始终对二级指数进行至少一次EQ比较?
答:二级索引的不等式总是在内存中完成,所以在另一个二级索引上至少没有一个EQ,你将加载数据库中的每一行,这对于一个庞大的数据库来说并不是一个好主意.因此,通过在(辅助)索引上要求至少一个EQ,您希望将需要读入内存的行集限制为可管理的大小.(虽然显然你仍然可以遇到麻烦).
所以基本上如果除了EQ比较之外还有其他东西,它会加载"与其他方式匹配"查询的所有行,并检查它们是否匹配,一次一个.默认情况下不允许这样做,因为它"可能很慢".(实质上,索引只是索引"for equality"而不是像<和>那样关系数据库上的哪些索引).
需要注意的一点是,如果您在二级索引上有多个非EQ条件,您还需要ALLOW FILTERING在查询中包含关键字,否则您将获得
Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING
一种简单的解决方法是在表中附加一个虚拟列,其中所有行在该列上具有相同的值.因此,在这种情况下,您只能对所需的列执行范围查询.要意识到NoSQL数据库上的这些查询可能会使系统变慢/陷入困境.
例
cqlsh:demo> desc table table1;
CREATE TABLE table1 (
keya int,
keyb int,
dummyvalue int,
valuea int,
PRIMARY KEY (keya, keyb)
) ....
cqlsh:demo> select * from Table1;
keya | keyb | dummyvalue | valuea
------+------+------------+--------
1 | 2 | 0 | 3
4 | 5 | 0 | 6
7 | 8 | 0 | 9
Run Code Online (Sandbox Code Playgroud)
在ValueA和DummyValue上创建二级索引:
cqlsh:demo> create index table1_valuea on table1 (valuea);
cqlsh:demo> create index table1_valueb on table1 (dummyvalue);
Run Code Online (Sandbox Code Playgroud)
上执行远程查询ValueA有DummyValue=0:
cqlsh:demo> select * from table1 where dummyvalue = 0 and valuea > 5 allow filtering;
keya | keyb | dummyvalue | valuea
------+------+------------+--------
4 | 5 | 0 | 6
7 | 8 | 0 | 9
Run Code Online (Sandbox Code Playgroud)
在 Cassandra 中处理这种情况的最灵活的方法可能是为每个统计数据都有一个单独的 CF,以哨兵值作为键,并将统计值放在列名称中,如下所示:
CF: StatName {
Key: SomeSentinelValue {
[Value]:[UserID] = ""
}
}
Run Code Online (Sandbox Code Playgroud)
假设您的统计数据是 NumAnswers,您的用户 ID 是字符串:
CF: NumAnswers {
Key: 0 {
150:Joe = ""
200:Bob = ""
500:Sue = ""
}
Key: 1000 {
1020:George = ""
1300:Ringo = ""
1300:Mary = ""
}
}
Run Code Online (Sandbox Code Playgroud)
因此,您可以看到,您的键本质上是值的存储桶,可以根据数据的需要粗粒度或细粒度,并且您的列是值 + 用户 ID 的组合。现在,您可以为 Cassandra 提供所需的粗略范围(相等性)的已知键(或键集),然后对列名的第一个组成部分执行范围查询。请注意,您不能将用户 ID 写入值,因为这会阻止两个用户具有相同的计数。