【问题标题】:Cassandra - How to retrieve most recent valueCassandra - 如何检索最新值
【发布时间】:2015-01-27 15:45:35
【问题描述】:

我在 Cassandra 2.0.9 中定义了下表:

CREATE TABLE history
(
    histid      uuid,
    ddate           text,       -- Day Date, i.e. 2014-11-20
    valtime         timestamp,  -- value time
    val             text,       --value
    PRIMARY KEY ((histid , ddate), valtime )
)
WITH CLUSTERING ORDER BY (valtime desc)
;

脚本每天都会在此表中插入数千行。

我需要能够从这个表中选择只知道 histid。 但是,我使用 (histid, ddate) 对行进行了分区。 意思是,我每行有一整天的历史值。

为了从该表中选择特定的 histid,我还需要提供 ddate 列。 例如:

SELECT * FROM history
WHERE histid= cebc4c80-daa6-11e3-bcc2-005056a975a4
AND ddate = '2014-05-16'
;

要获取最新值,我可以执行以下操作:

SELECT * FROM history
WHERE histid= cebc4c80-daa6-11e3-bcc2-005056a975a4
AND ddate = '2014-05-16'
LIMIT 1
;

但是,如果我想要任何给定 histid 的最新值,我无法在不知道 ddate 是什么的情况下提交查询,因为它是分区键的一部分。

所以...我问,解决这个问题的最佳方法是什么?

这是我所做的,但我不知道这是否合理:

我创建了一个辅助表:

 CREATE TABLE history_date
(
    histid          uuid,
    maxdate         timestamp, -- most recent date
    PRIMARY KEY (histid)
);

当向历史表中插入一行时,也会使用 (histid, valtime) 向该表中插入一行。

然后我们的程序代码可以:

1.  query the history_date table for a particular id
2. take the "maxdate" column (truncate it to yyyy-mm-dd)
3. use the histid and truncated maxdate to query the history table to retrieve the most recent value.

所以这行得通。但是,这并不是一个好的解决方案。

有没有更好的方法来做到这一点,也许只用一张桌子?

感谢您的宝贵时间。

【问题讨论】:

  • Cassandra 的数据建模是一种不同的思维方式,采用冗余数据/查询表的方法是正确的。
  • @BryceAtNetwork23 - 谢谢。是的,有时很难绕开你的脑袋。感谢您的反馈。
  • @iamtheoracle 这很难。关键是要认识到需要一种不同的心态,并且你已经通过了那个障碍,所以你走在正确的道路上。比许多似乎从未“明白”的人更进一步。 :) 坚持下去,随着时间的推移,它会变得更有意义。
  • @DonBranson 感谢 20 多年使用“其他”主要数据库已经毁了我 :)
  • @iamtheoracle 呵呵。好吧,我已经编码足够长的时间了,以至于我记得上一次范式转变 SQL数据库。

标签: cassandra cassandra-2.0 composite-primary-key


【解决方案1】:

您可以尝试的一件事是构建一个在更广泛的日期范围内分区的新表,例如month。这样,您只需要知道要查询的月份。

CREATE TABLE history_by_month(
    histid          uuid,
    ddate           text,       -- Day Date, i.e. 2014-11-20
    valtime         timestamp,  -- value time
    val             text,       --value
    month           text,
    PRIMARY KEY (month, valtime, histid))
WITH CLUSTERING ORDER BY (valtime desc, histid asc);

现在,此查询应返回您要查找的内容:

SELECT * FROM history_by_month
WHERE month = '2014-05'
LIMIT 1;

唯一要记住的是,如果您在一个月内获得太多条目,则您的分区可能会太大。如果这成为一个问题,您可能会考虑将重点缩小到一周。

此外,仍在使用 2.0.9 的任何人都应该考虑升级。即使是最新的 2.1 补丁级别也更加更加稳定。

【讨论】:

  • 拥有更大的分区并不能解决问题。这仍然是同一个问题:我如何确定用于查询的月份。我只是想知道除了OP提出的一个通用解决方案之外是否有通用解决方案?
  • @IhorKaharlichenko 不幸的是,Cassandra 有非常严格的查询要求,因此需要了解一些时间范围来缩小范围。
【解决方案2】:

好吧,正如您所提到的,您不能只知道使用两个键分区的表的一个值来选择。但是,您已经使用过的聚类顺序和按限制顺序选项可能会有所帮助。

http://www.datastax.com/documentation/cql/3.1/cql/cql_reference/refClstrOrdr.html

https://cassandra.apache.org/doc/cql3/CQL.html#selectStmt

【讨论】:

    【解决方案3】:

    我认为解决方案是直截了当的,没有必要把事情复杂化。 只需在“histid”上创建分区键,在“ddate”上创建集群键。所以你的 DDL 应该如下所示

    创建表历史 ( histid uuid, 日期文本, valtime时间戳, 验证文本, 主键 ((histid) , ddate, valtime ) ) ;

    您可以从以下任意组合进行查询(但要确保 where 子句中的顺序相同) a) 仅查询 histid b) 查询 histid 和 dddate c) 查询 histid 、 dddate 和 valtime

    让我知道这是否适合您或您仍有疑问?

    【讨论】:

      猜你喜欢
      • 2011-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-07
      相关资源
      最近更新 更多