最近在使用Cassandra,版本为1.1.1, CQL版本为3.0.0。遇到如下问题。
目标:利用复合主键进行查询和排序,并想利用二级索引进行多条件查询。
首先CQL建表,用到复合主键(instigator, startedAt):
CREATE TABLE altercations ( instigator text, startedAt text, shipsDestroyed text, energyUsed text,allianceInvolvement text, PRIMARY KEY (instigator, startedAt) );
然后建立二级索引:
CREATE INDEX ON altercations (shipsDestroyed);
执行CREATE INDEX 操作后,Cassandra报错:
java.lang.IllegalArgumentException at java.nio.Buffer.limit(Buffer.java:249) at org.apache.cassandra.db.marshal.AbstractCompositeType.getBytes(AbstractCompositeType.java:51) at org.apache.cassandra.db.marshal.AbstractCompositeType.getWithShortLength(AbstractCompositeType.java:60) at org.apache.cassandra.db.marshal.AbstractCompositeType.getString(AbstractCompositeType.java:140) at org.apache.cassandra.config.CFMetaData.getDefaultIndexName(CFMetaData.java:875) at org.apache.cassandra.config.CFMetaData.addDefaultIndexNames(CFMetaData.java:863) at org.apache.cassandra.cql3.statements.CreateIndexStatement.announceMigration(CreateIndexStatement.java:90) at org.apache.cassandra.cql3.statements.SchemaAlteringStatement.execute(SchemaAlteringStatement.java:99) at org.apache.cassandra.cql3.QueryProcessor.processStatement(QueryProcessor.java:108) at org.apache.cassandra.cql3.QueryProcessor.process(QueryProcessor.java:121) at org.apache.cassandra.thrift.CassandraServer.execute_cql_query(CassandraServer.java:1237) at org.apache.cassandra.thrift.Cassandra$Processor$execute_cql_query.getResult(Cassandra.java:3542) at org.apache.cassandra.thrift.Cassandra$Processor$execute_cql_query.getResult(Cassandra.java:3530) at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:32) at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:34) at org.apache.cassandra.thrift.CustomTThreadPoolServer$WorkerProcess.run(CustomTThreadPoolServer.java:186) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619)
但是,把复合主键改为单一主键的话,这个错误是没有的。
经过一天的思考,发现确实不能建立二级索引了。
本人对二级索引建立的内部原理不是很清楚,但参考Apache Cassandra 1.1 Documentation,发现确实只能用主键查询(就是多建几个主键),而且多条件查询时(除最后一个外)必须用“=”表达式。
比如像这样:
建表:
CREATE TABLE altercations ( instigator text, startedAt text, shipsDestroyed text, energyUsed text, allianceInvolvement text, PRIMARY KEY (instigator, startedAt, shipsDestroyed) );
查询:
SELECT * FROM altercations WHERE instigator='Jayne Cobb' AND startedAt = '7943-06-23' AND shipsDestroyed>'3' ORDER BY startedAt DESC;
.===============分隔符============================
问题:
后来,有添加了一个复合主键, 建表语句为:
CREATE TABLE altercations ( instigator text, startedAt text, shipsDestroyed text, energyUsed text, allianceInvolvement text, PRIMARY KEY (instigator, startedAt, shipsDestroyed, energyUsed) );
查询语句:
SELECT * FROM altercations WHERE instigator='Jayne Cobb' AND startedAt = '7943-06-23' AND shipsDestroyed='3' AND energyUsed>'4.6' ORDER BY startedAt DESC;
发现搜索出的结果完全混乱了,根本不是按条件查询出来的,如下:
instigator : Jayne Cobb; startedat : 7943-06-24; shipsdestroyed : 7; energyused : 4.6; allianceinvolvement : false; gender : null;
instigator : Jayne Cobb; startedat : 7943-06-24; shipsdestroyed : 6; energyused : 4.6; allianceinvolvement : false; gender : null;
instigator : Jayne Cobb; startedat : 7943-06-24; shipsdestroyed : 5; energyused : 4.6; allianceinvolvement : false; gender : null;
instigator : Jayne Cobb; startedat : 7943-06-23; shipsdestroyed : 4; energyused : 4.6; allianceinvolvement : false; gender : null;
还不清楚怎么回事! 主要就是 energyUsed>'4.6' 这个判断条件,改为 energyUsed='4.6' 是没问题的。