Optimization 在基于时间的小数据块中查询cassandra的最有效方法
我的基于Cassandra的应用程序需要读取自上次读取以来更改的行。 为此,我们计划创建一个表Optimization 在基于时间的小数据块中查询cassandra的最有效方法,optimization,cassandra,datastax,cql,cqlsh,Optimization,Cassandra,Datastax,Cql,Cqlsh,我的基于Cassandra的应用程序需要读取自上次读取以来更改的行。 为此,我们计划创建一个表changed\u rows,其中包含两列- ID—已更改行的ID和 Updated_Time-更改时的时间戳 读取这样一个表的最佳方式是什么,这样它就可以读取按时间排序的一小组行。 示例:如果表格为: ID Updated_Time foo 1000 bar 1200 abc 2000 pqr 2500 zyx 2900 ... xyz 901000 ...
changed\u rows
,其中包含两列-
ID Updated_Time
foo 1000
bar 1200
abc 2000
pqr 2500
zyx 2900
...
xyz 901000
...
我已经展示了ID是简单的3字母键,实际上它们是UUID。
此外,为了简单起见,上面显示的时间显示为整数,但它是实际的Cassandra时间戳(或Java日期)更新时间列是单调递增的。
如果我使用以下方法查询此数据:
SELECT * FROM changed_rows WHERE Updated_Time < toTimestamp(now())
但是我认为允许过滤
在这种情况下会破坏性能。
Cassandra索引页面警告避免索引高基数列,并且上面的Updated\u Time
看起来像是高基数
我不知道前面的ID列,因为查询的目的是知道在给定的时间间隔之间更新的ID
在这种情况下,查询Cassandra的最佳方式是什么?我能否以某种方式更改表以更高效地运行时间块查询
注意:这听起来应该有点类似,但我们不能使用相同的解决方案,因为我们的解决方案应该适用于所有Cassandra版本假设您知道要查询的时间间隔,您需要创建另一个表,如下所示:
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);
您使用updateTime
时间戳的一部分作为分区键,例如在本例中,您四舍五入到整数小时。然后通过仅指定时间段进行查询,例如:
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分钟一次。这种结构非常灵活。您只需要知道要查询的时隙。如果需要跨越多个时隙,则需要执行多个查询。如果知道要查询的时间间隔,则需要创建另一个表,如下所示:
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);
您使用updateTime
时间戳的一部分作为分区键,例如在本例中,您四舍五入到整数小时。然后通过仅指定时间段进行查询,例如:
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分钟一次。这种结构非常灵活。您只需要知道要查询的时隙。如果需要跨越多个时隙,则需要执行多个查询。为什么不使用“主键(时隙)”呢?据我所知,由于时隙和UpdateTime都是分区键的一部分,您的选择将不起作用。@starikoff:它们都是主键的一部分,但实际上只有
timeslot
是分区键,UpdateTime
是群集键。我的错,我已经有一段时间没有看到分区键周围没有显式括号的键规范了,所以我(错误地)认为,如果没有它们,所有部分都会形成一个复合分区键。Cassandra是否有一个函数以某种方式返回dayOfYear
fromnow()
?这样我就可以用它来自动填充我的列了?示例:插入修改的_记录(时隙、更新时间、记录ID)值(dayOfYear(now())、toTimestamp(now())、789)
@user2250246我不这么认为。另外,我不太喜欢查询中的函数(比如now()
),因为它们倾向于从查询中删除幂等性。当然,这取决于具体情况。。。。顺便说一句,您可以在客户端代码中轻松解决这个问题,如果您有小时/分钟的时隙,您可能真的需要这样做……为什么不使用“主键(时隙)”呢?据我所知,由于时隙和UpdateTime都是分区键的一部分,您的选择将不起作用。@starikoff:它们都是主键的一部分,但实际上只有timeslot
是分区键,UpdateTime
是群集键。我的错,我已经有一段时间没有看到分区键周围没有显式括号的键规范了,所以我(错误地)认为,如果没有它们,所有部分都会形成一个复合分区键。Cassandra是否有一个函数以某种方式返回dayOfYear
fromnow()
?这样我就可以用它来自动填充我的列了?示例:插入修改的_记录(时隙、更新时间、记录ID)值(dayOfYear(now())、toTimestamp(now())、789)
@user2250246我不这么认为。另外,我不太喜欢查询中的函数(比如now()
),因为它们倾向于从查询中删除幂等性。当然,这取决于具体情况。。。。顺便说一句,您可以在客户端代码中轻松解决这个问题,如果您有小时/分钟的时间段,您可能真的需要解决这个问题。。。