【问题标题】:Most efficient way to query cassandra in small time-based chunks在基于时间的小块中查询 cassandra 的最有效方法
【发布时间】:2017-07-17 12:27:41
【问题描述】:

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

  1. ID - 更改行的 ID 和
  2. Updated_Time - 更改时的时间戳。

读取这样一个表的最佳方法是什么,以便它读取按时间排序的一小组行。 示例:如果表是:

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 版本

【问题讨论】:

    标签: optimization cassandra datastax cql cqlsh


    【解决方案1】:

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

    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 分钟。这种结构非常灵活。您只需要知道您要查询的时间段。如果您需要跨越多个时隙,则需要执行多个查询。

    【讨论】:

    • 为什么不是“主键(时隙)”?据我了解,时间段和更新时间都是分区键的一部分,因此您的 SELECT 将不起作用。
    • @starikoff:它们都是主键的一部分,但实际上只有timeslot分区键updatedtime是聚类键。
    • 我的错,我已经有一段时间没有看到没有围绕分区键的显式括号的键规范了,所以我(错误地)认为没有它们,所有部分都会形成一个复合分区键。
    • Cassandra 是否具有以某种方式从now() 返回dayOfYear 的功能?这样我就可以使用它来自动填充我的列?示例:INSERT INTO modified_records (timeslot, updatedtime, recordid) VALUES (dayOfYear(now()), toTimestamp(now()), 789)
    • @user2250246 我不这么认为。此外,我不太喜欢查询中的函数(如now()),因为它们倾向于从查询中删除幂等性。当然,这取决于具体情况....顺便说一句,您可以在客户端代码中轻松解决这个问题,如果您有小时/分钟时间段,您可能真的需要...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    • 2020-06-12
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    相关资源
    最近更新 更多