Uploaded image for project: 'Apache Cassandra'
  1. Apache Cassandra
  2. CASSANDRA-11734

Enable partition component index for SASI

    XMLWordPrintableJSON

Details

    Description

      Enable partition component index for SASI

      For the given schema:

      CREATE TABLE test.comp (
          pk1 int,
          pk2 text,
          val text,
          PRIMARY KEY ((pk1, pk2))
      );
      
      CREATE CUSTOM INDEX comp_val_idx ON test.comp (val) USING 'org.apache.cassandra.index.sasi.SASIIndex';
      CREATE CUSTOM INDEX comp_pk2_idx ON test.comp (pk2) USING 'org.apache.cassandra.index.sasi.SASIIndex' WITH OPTIONS = {'mode': 'PREFIX', 'analyzer_class': 'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer', 'case_sensitive': 'false'};
      CREATE CUSTOM INDEX comp_pk1_idx ON test.comp (pk1) USING 'org.apache.cassandra.index.sasi.SASIIndex';
      

      The following queries are possible:

      SELECT * FROM test.comp WHERE pk1=1;
      SELECT * FROM test.comp WHERE pk1>=1 AND pk1<=5;
      
      SELECT * FROM test.comp WHERE pk1=1 AND val='xxx' ALLOW FILTERING;
      SELECT * FROM test.comp WHERE pk1>=1 AND pk1<=5 AND val='xxx' ALLOW FILTERING;
      
      SELECT * FROM test.comp WHERE pk2='some text';
      SELECT * FROM test.comp WHERE pk2 LIKE 'prefix%';
      
      SELECT * FROM test.comp WHERE pk2='some text' AND val='xxx' ALLOW FILTERING;
      SELECT * FROM test.comp WHERE pk2 LIKE 'prefix%' AND val='xxx' ALLOW FILTERING;
      
      //Without using SASI
      SELECT * FROM test.comp WHERE pk1 = 1 AND pk2='some text';
      SELECT * FROM test.comp WHERE pk1 IN(1,2,3) AND pk2='some text';
      
      SELECT * FROM test.comp WHERE pk1 = 1 AND pk2 IN ('text1','text2');
      SELECT * FROM test.comp WHERE pk1 IN(1,2,3) AND pk2 IN ('text1','text2');
      

      However, the following queries are not possible

      SELECT * FROM test.comp WHERE pk1=1 AND pk2 LIKE 'prefix%';
      
      SELECT * FROM test.comp WHERE pk1>=1 AND pk1<=5 AND pk2 = 'some text';
      
      SELECT * FROM test.comp WHERE pk1>=1 AND pk1<=5 AND pk2 LIKE 'prefix%';
      

      All of them are throwing the following exception

      ava.lang.UnsupportedOperationException: null
      	at org.apache.cassandra.cql3.restrictions.SingleColumnRestriction$LikeRestriction.appendTo(SingleColumnRestriction.java:715) ~[main/:na]
      	at org.apache.cassandra.cql3.restrictions.PartitionKeySingleRestrictionSet.values(PartitionKeySingleRestrictionSet.java:86) ~[main/:na]
      	at org.apache.cassandra.cql3.restrictions.StatementRestrictions.getPartitionKeys(StatementRestrictions.java:585) ~[main/:na]
      	at org.apache.cassandra.cql3.statements.SelectStatement.getSliceCommands(SelectStatement.java:473) ~[main/:na]
      	at org.apache.cassandra.cql3.statements.SelectStatement.getQuery(SelectStatement.java:265) ~[main/:na]
      	at org.apache.cassandra.cql3.statements.SelectStatement.execute(SelectStatement.java:230) ~[main/:na]
      	at org.apache.cassandra.cql3.statements.SelectStatement.execute(SelectStatement.java:79) ~[main/:na]
      	at org.apache.cassandra.cql3.QueryProcessor.processStatement(QueryProcessor.java:208) ~[main/:na]
      	at org.apache.cassandra.cql3.QueryProcessor.process(QueryProcessor.java:239) ~[main/:na]
      	at org.apache.cassandra.cql3.QueryProcessor.process(QueryProcessor.java:224) ~[main/:na]
      	at org.apache.cassandra.transport.messages.QueryMessage.execute(QueryMessage.java:115) ~[main/:na]
      	at org.apache.cassandra.transport.Message$Dispatcher.channelRead0(Message.java:507) [main/:na]
      	at org.apache.cassandra.transport.Message$Dispatcher.channelRead0(Message.java:401) [main/:na]
      	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-all-4.0.36.Final.jar:4.0.36.Final]
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292) [netty-all-4.0.36.Final.jar:4.0.36.Final]
      	at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:32) [netty-all-4.0.36.Final.jar:4.0.36.Final]
      	at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:283) [netty-all-4.0.36.Final.jar:4.0.36.Final]
      	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_45]
      	at org.apache.cassandra.concurrent.AbstractLocalAwareExecutorService$FutureTask.run(AbstractLocalAwareExecutorService.java:164) [main/:na]
      	at org.apache.cassandra.concurrent.SEPWorker.run(SEPWorker.java:106) [main/:na]
      

      Indeed, to allow the above queries we'll need to update the class StatementRestrictions and introduce a new class PartitionKeyMultipleRestrictionsSet and I don't feel like doing it, afraid of breaking existing code.

      WDYT xedin jrwest blerer ?

      I attach a patch for this JIRA.

      I have added new tests to OperationTest and SASIIndexTest with flushing & non-flushing before queries to test in-memory & on disk read paths.

      To enable operators other than = and IN on the partition key component, I modified the SingleColumnRelation to add this code:

       else if (isSlice() || isLIKE())
              {
                  // Non EQ relation is not supported without token(), unless SASI index is used
                  final boolean hasSASIIndex = metaData.getLiveIndices()
                                            .stream()
                                            .filter(index -> index.dependsOn(columnDef))
                                            .anyMatch(index -> index instanceof SASIIndex);
      
                  checkFalse(columnDef.isPartitionKey() && !hasSASIIndex, "Only EQ and IN relation are supported on the partition key (unless you use the token() function or SASI index)");
              }
      

      This implies adding the method getLiveIndices() on CFMetaData which accesses the index manager by creating an instance of ColumnFamilyStore, don't know whether it is expensive or not, please advise

      //CFMetaData
          public Collection<Index> getLiveIndices()
          {
              return Keyspace.openAndGetStore(this).indexManager.listIndexes();
          }
      
      

      Attachments

        1. patch.txt
          48 kB
          DuyHai Doan

        Issue Links

          Activity

            People

              doanduyhai DuyHai Doan
              doanduyhai DuyHai Doan
              DuyHai Doan
              Pavel Yaskevich
              Votes:
              3 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

                Created:
                Updated: