在基于时间的小块中查询cassandra的最有效方法

时间:2017-02-27 01:34:59

标签: optimization cassandra datastax cql cqlsh

我的基于Cassandra的应用程序需要读取自上次读取后更改的行。 为此,我们计划有一个表changed_rows,其中包含两列 -

  1. ID - 已更改行的ID和
  2. Updated_Time - 更改时间戳。
  3. 读取这样一个表的最佳方法是什么,它读取按时间排序的小组行。 示例:如果表格为:

    ID   Updated_Time
    foo    1000
    bar    1200
    abc    2000
    pqr    2500
    zyx    2900
     ...
    xyz   901000
     ...
    

    我已将ID显示为简单的3字母键,实际上它们是UUID。 此外,为简单起见,上面显示的时间显示为整数,但它是实际的Cassandra时间戳(或Java日期)。 Updated_Time列是单调增加的列。

    如果我用以下方式查询此数据:

    SELECT * FROM changed_rows WHERE Updated_Time < toTimestamp(now())
    

    我收到以下错误:

    Cannot execute this query as it might involve data filtering and 
    thus may have unpredictable performance... Use Allow Filtering
    

    但我认为Allow Filtering在这种情况下会导致性能下降。 Cassandra索引页面警告要避免使用高基数列的索引,并且上面的Updated_Time看起来确实像高基数。

    我之前不知道ID列,因为查询的目的是知道在给定时间间隔内更新的ID。

    在这种情况下查询Cassandra的最佳方法是什么呢? 我可以以某种方式更改我的表以更有效地运行时间块查询吗?

    注意:这听起来应该与Cassandra-CDC feature有些相似,但我们不能使用相同的,因为我们的解决方案适用于所有Cassandra版本

1 个答案:

答案 0 :(得分:2)

假设您知道要查询的时间间隔,则需要创建另一个表,如下所示:

CREATE TABLE modified_records (
    timeslot timestamp,
    updatedtime timestamp,
    recordid timeuuid,
    PRIMARY KEY (timeslot, updatedtime)
);

现在您可以将“更新的记录日志”拆分为时间片,例如1小时,并填写如下表:

INSERT INTO modified_records (timeslot, updatedtime, recordid) VALUES ( '2017-02-27 09:00:00', '2017-02-27 09:36:00', 123);
INSERT INTO modified_records (timeslot, updatedtime, recordid) VALUES ( '2017-02-27 09:00:00', '2017-02-27 09:56:00', 456);
INSERT INTO modified_records (timeslot, updatedtime, recordid) VALUES ( '2017-02-27 10:00:00', '2017-02-27 10:00:13', 789);

您使用updatedtime时间戳的一部分作为分区键,例如在这种情况下,您将舍入到整数小时。然后通过仅指定时隙进行查询,例如:

SELECT * FROM modified_records WHERE timeslot = '2017-02-27 09:00:00';
SELECT * FROM modified_records WHERE timeslot = '2017-02-27 10:00:00';

根据记录更新的频率,您可以使用更小或更大的时间片,例如每6小时,1天或每15分钟。这种结构非常灵活。您只需要知道要查询的时间段。如果您需要跨越多个时隙,则需要执行多个查询。