Cassandra: Query with where clause containing greather- or lesser-than (< and>)

前端 未结 2 1439
情书的邮戳
情书的邮戳 2021-01-12 08:27

I\'m using Cassandra 1.1.2 I\'m trying to convert a RDBMS application to Cassandra. In my RDBMS application I have following table called table1:

| Col1 | C         


        
相关标签:
2条回答
  • 2021-01-12 08:33

    Cassandra indexes don't actually support sequential access; see http://www.datastax.com/docs/1.1/ddl/indexes for a good quick explanation of where they are useful. But don't despair; the more classical way of using Cassandra (and many other NoSQL systems) is to denormalize, denormalize, denormalize.

    It may be a good idea in your case to use the classic bucket-range pattern, which lets you use the recommended RandomPartitioner and keep your rows well distributed around your cluster, while still allowing sequential access to your values. The idea in this case is that you would make a second dynamic columnfamily mapping (bucketed and ordered) col3 values back to the related primary_key values. As an example, if your col3 values range from 0 to 10^9 and are fairly evenly distributed, you might want to put them in 1000 buckets of range 10^6 each (the best level of granularity will depend on the sort of queries you need, the sort of data you have, query round-trip time, etc). Example schema for cql3:

    CREATE TABLE indexotron (
        rangestart int,
        col3val int,
        table1key varchar,
        PRIMARY KEY (rangestart, col3val, table1key)
    );
    

    When inserting into table1, you should insert a corresponding row in indexotron, with rangestart = int(col3val / 1000000). Then when you need to enumerate all rows in table1 with col3 > X, you need to query up to 1000 buckets of indexotron, but all the col3vals within will be sorted. Example query to find all table1.primary_key values for which table1.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;
    
    0 讨论(0)
  • 2021-01-12 08:45

    If col3 is always known small values/ranges, you may be able to get away with a simpler table that also maps back to the initial table, ex:

     create table table2 (col3val int, table1key varchar,
                          primary key (col3val, table1key));
    

    and use

     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;
     ...
    

    Or

     select * from table2 where col3val  in (51, 52, ...);
    

    Maybe OK if you don't have too large of ranges. (you could get the same effect with your secondary index as well, but secondary indexes aren't highly recommended?). Could theoretically parallelize it "locally on the client side" as well.

    It seems the "Cassandra way" is to have some key like "userid" and you use that as the first part of "all your queries" so you may need to rethink your data model, then you can have queries like select * from table1 where userid='X' and col3val > 3 and it can work (assuming a clustering key on col3val).

    0 讨论(0)
提交回复
热议问题