【问题标题】:Cassandra get latest entry for each element contained within IN clauseCassandra 获取 IN 子句中包含的每个元素的最新条目
【发布时间】:2017-09-11 19:36:06
【问题描述】:

所以,我有一个 Cassandra CQL 语句,如下所示:

SELECT * FROM DATA WHERE APPLICATION_ID = ? AND PARTNER_ID = ? AND LOCATION_ID = ? AND DEVICE_ID = ? AND DATA_SCHEMA = ?

此表按时间戳列排序。

该功能由 REST API 和他们可以指定以获取最新行的过滤器参数之一,然后我将“LIMIT 1”附加到 CQL 语句的末尾,因为它是按时间戳排序的列按降序排列。我想做的是允许他们指定多个设备 ID 以获取最新条目。所以,我的问题是,有没有办法在 Cassandra 中做这样的事情:

SELECT * FROM DATA WHERE APPLICATION_ID = ? AND PARTNER_ID = ? AND LOCATION_ID = ? AND DEVICE_ID IN ? AND DATA_SCHEMA = ?

并且仍然使用“LIMIT 1”之类的东西来只取回每个设备 ID 的最新行?或者,我是否只需为每个设备执行单独的 CQL 语句来获取每个设备的最新行?

FWIW,表的复合键如下所示:

PRIMARY KEY ((application_id, partner_id, location_id, device_id, data_schema), activity_timestamp)
) WITH CLUSTERING ORDER BY (activity_timestamp DESC);

【问题讨论】:

    标签: cassandra cql


    【解决方案1】:

    当它有很多参数时,不建议使用 IN,并且在后台它无论如何都会对多个分区进行请求,并且它会对协调节点施加压力。

    并不是说你做不到。这是完全合法的,但大多数情况下它的性能不佳且不建议使用。如果你指定limit,它是针对整个语句的,基本上你不能从分区中只选择第一项。最简单的选择是向集群发出多个查询(IN 中的每个元素都将成为一个查询)并将limit 1 放入其中。

    说实话,这是我在很多项目中的解决方案,而且效果很好。基本上,协调员无论如何都会在后台转到多个节点,但也必须为您做更多工作才能获得所有请求,可能会遇到超时等。

    简而言之,如果客户端多次请求(使用具有较小请求的多个协调器)比让单个协调器完成所有工作,这对集群来说要好得多,性能也更高。

    这是万一您无法为集群提供更多磁盘空间的情况

    通常的 Cassandra 解决方案

    建议 cassandra 中的数据准备好进行查询(先查询)。所以基本上你必须有一个额外的表,它与你现在拥有的分区键相同,你必须删除集群列activity_timestamp。即

    PRIMARY KEY ((application_id, partner_id, location_id, device_id, data_schema))
    

    double (()) 是故意的。

    每次您写入表时,您也会将数据写入latest_entry(没有activity_timestamp 的表)然后您可以指定您需要的查询,该表包含最新条目,因此您不需要不必使用限制 1,因为每个分区键只有一个条目......这将是 cassandra 中的常用解决方案。

    如果您害怕额外的写入,请不要担心,它们价格低廉且受 CPU 限制。使用 cassandra,我猜它总是“带来写入”:)

    基本上由你决定:

    1. 多个查询 - 一点重构,没有额外的空间成本
    2. 新架构 - 写入时额外插入,额外空间成本

    【讨论】:

    • 谢谢!这几乎就是我的想法,但我对 Cassandra 还很陌生,所以只是想确保我没有遗漏任何东西。我已经在每次插入到另一个正在跟踪一些其他内容的表中进行额外的写入,因此只拥有另一个只跟踪最新条目的表可能不会有什么大不了的。我认为它会帮助提高性能,在这里性能肯定比它消耗的一点点空间更重要:)
    • 好吧,那么你们都很好;)伙计,这个项目看起来很有趣:)哦,设备写入的频率是多少。如果它是更频繁地写入的东西,请考虑使用分桶让我们说每隔几秒钟或更频繁地我可以给出一些建议;)只是说频率
    • 我得调查一下——我没听说过分桶。目前每个“容器”的写入频率是每 5 秒一次,并且容器的数量有望继续快速增长,因此每 5 秒将有 x 次写入,这可能是一个很大的数目。
    • 每个“桶”每天大约有 17k 个条目,我们有类似的负载,我们按月分桶。基本上一个月内来自一个传感器的所有数据都在一个月分区中。这一切都取决于负载。这是一个答案stackoverflow.com/questions/39446962/… 也可以尝试谷歌。这将为您节省很多麻烦;)
    • 我还发现更新有点晚,因为您的问题正在寻找其他东西,看起来 cassandra 的任何版本都不会支持每个分区限制:docs.datastax.com/en/cql/3.3/cql/cql_using/… 所以基本上你可以使用 PER PARTITION LIMIT 1; 但我会暂时远离 3.0.X 以外的版本,它们似乎有点不稳定。
    【解决方案2】:

    您的表定义不适合这样使用 IN 子句。实际上,它在主键的最后一个字段或集群键的最后一个字段上受支持。所以你可以:

    • 交换主键的最后两个字段
    • 对每个设备 ID 使用一个查询

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-26
      • 2020-11-18
      • 2021-09-28
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多