我的基于Cassandra的应用程序需要读取自上次读取后更改的行。
为此,我们计划有一个表changed_rows
,其中包含两列 -
读取这样一个表的最佳方法是什么,它读取按时间排序的小组行。 示例:如果表格为:
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版本
答案 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分钟。这种结构非常灵活。您只需要知道要查询的时间段。如果您需要跨越多个时隙,则需要执行多个查询。