在基于时间的小块中查询 cassandra 的最有效方法
Most efficient way to query cassandra in small time-based chunks
我的基于 Cassandra 的应用程序需要读取自上次读取后更改的行。
为此,我们计划有一个包含两列的 table changed_rows
-
- ID - 更改行的 ID 和
- Updated_Time - 更改时的时间戳。
读取这样一个 table 的最佳方法是什么,以便它读取按时间排序的一小组行。
示例:如果 table 是:
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 的最佳方式是什么?
我能否以某种方式将我的 table 更有效地更改为 运行 时间块查询?
注意:这听起来应该与 Cassandra-CDC feature 有点相似,但我们不能使用相同的方法,因为我们的解决方案应该适用于所有 Cassandra 版本
假设您知道要查询的时间间隔,则需要创建另一个 table,如下所示:
CREATE TABLE modified_records (
timeslot timestamp,
updatedtime timestamp,
recordid timeuuid,
PRIMARY KEY (timeslot, updatedtime)
);
现在您可以将 "updated record log" 分成时间片,例如 1 小时,然后像这样填充 table:
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 分钟。这种结构非常灵活。您只需要知道您要查询的时间段。如果您需要跨越多个时隙,则需要执行多个查询。
我的基于 Cassandra 的应用程序需要读取自上次读取后更改的行。
为此,我们计划有一个包含两列的 table changed_rows
-
- ID - 更改行的 ID 和
- Updated_Time - 更改时的时间戳。
读取这样一个 table 的最佳方法是什么,以便它读取按时间排序的一小组行。 示例:如果 table 是:
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 的最佳方式是什么?
我能否以某种方式将我的 table 更有效地更改为 运行 时间块查询?
注意:这听起来应该与 Cassandra-CDC feature 有点相似,但我们不能使用相同的方法,因为我们的解决方案应该适用于所有 Cassandra 版本
假设您知道要查询的时间间隔,则需要创建另一个 table,如下所示:
CREATE TABLE modified_records (
timeslot timestamp,
updatedtime timestamp,
recordid timeuuid,
PRIMARY KEY (timeslot, updatedtime)
);
现在您可以将 "updated record log" 分成时间片,例如 1 小时,然后像这样填充 table:
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 分钟。这种结构非常灵活。您只需要知道您要查询的时间段。如果您需要跨越多个时隙,则需要执行多个查询。