Cassandra 获取 IN 子句中包含的每个元素的最新条目
Cassandra get latest entry for each element contained within IN clause
所以,我有一个如下所示的 Cassandra CQL 语句:
SELECT * FROM DATA WHERE APPLICATION_ID = ? AND PARTNER_ID = ? AND LOCATION_ID = ? AND DEVICE_ID = ? AND DATA_SCHEMA = ?
此 table 按时间戳列排序。
该功能前面是 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,table 的复合键如下所示:
PRIMARY KEY ((application_id, partner_id, location_id, device_id, data_schema), activity_timestamp)
) WITH CLUSTERING ORDER BY (activity_timestamp DESC);
IN is not recommended when there are a lot of parameters for it and under the hood it's making reqs to multiple partitions anyway and it's putting pressure on the coordinator node.
并不是说你做不到。这是完全合法的,但大多数时候它的性能不佳,因此不建议使用。如果你指定限制,它是针对整个语句的,基本上你不能只从分区中选择第一项。最简单的选择是向集群发出多个查询(IN
中的每个元素都将成为一个查询)并对每个元素放置一个 limit 1
。
老实说,这是我在很多项目中的解决方案,而且效果非常好。基本上,协调器无论如何都会在幕后转到多个节点,但也必须为您做更多工作才能获得所有请求,可能 运行 超时等
In short it's far better for the cluster and more performant if client asks multiple times (using multiple coordinators with smaller requests) than to make single coordinator do to all the work.
这是为了防止您无法为您的集群space提供更多磁盘
通常的 Cassandra 解决方案
cassandra中的数据建议准备好查询(先查询)。所以基本上你必须有一个额外的 table 与你现在有相同的分区键,你将不得不删除集群列 activity_timestamp
。即
PRIMARY KEY ((application_id, partner_id, location_id, device_id, data_schema))
double (())
是故意的。
每次你写你的table你也会写数据到latest_entry
(table没有activity_timestamp
)然后你可以指定你的查询需要 in 并且此 table 包含最新条目,因此您不必使用限制 1 因为每个分区键只有一个条目......这将是 cassandra 中的常用解决方案。
如果您害怕额外的写入,请不要担心,它们很便宜并且 cpu 受限。对于 cassandra,我猜它总是 "bring on the writes" :)
基本上由您决定:
- 多个查询 - 一些重构,没有额外的 space 成本
- 新模式 - 写入时额外插入,额外 space 成本
您的 table 定义不适合 table IN 子句的此类使用。实际上,它在主键的最后一个字段或集群键的最后一个字段上受支持。所以你可以:
- 交换主键的最后两个字段
- 对每个设备 ID 使用一个查询
所以,我有一个如下所示的 Cassandra CQL 语句:
SELECT * FROM DATA WHERE APPLICATION_ID = ? AND PARTNER_ID = ? AND LOCATION_ID = ? AND DEVICE_ID = ? AND DATA_SCHEMA = ?
此 table 按时间戳列排序。
该功能前面是 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,table 的复合键如下所示:
PRIMARY KEY ((application_id, partner_id, location_id, device_id, data_schema), activity_timestamp)
) WITH CLUSTERING ORDER BY (activity_timestamp DESC);
IN is not recommended when there are a lot of parameters for it and under the hood it's making reqs to multiple partitions anyway and it's putting pressure on the coordinator node.
并不是说你做不到。这是完全合法的,但大多数时候它的性能不佳,因此不建议使用。如果你指定限制,它是针对整个语句的,基本上你不能只从分区中选择第一项。最简单的选择是向集群发出多个查询(IN
中的每个元素都将成为一个查询)并对每个元素放置一个 limit 1
。
老实说,这是我在很多项目中的解决方案,而且效果非常好。基本上,协调器无论如何都会在幕后转到多个节点,但也必须为您做更多工作才能获得所有请求,可能 运行 超时等
In short it's far better for the cluster and more performant if client asks multiple times (using multiple coordinators with smaller requests) than to make single coordinator do to all the work.
这是为了防止您无法为您的集群space提供更多磁盘
通常的 Cassandra 解决方案
cassandra中的数据建议准备好查询(先查询)。所以基本上你必须有一个额外的 table 与你现在有相同的分区键,你将不得不删除集群列 activity_timestamp
。即
PRIMARY KEY ((application_id, partner_id, location_id, device_id, data_schema))
double (())
是故意的。
每次你写你的table你也会写数据到latest_entry
(table没有activity_timestamp
)然后你可以指定你的查询需要 in 并且此 table 包含最新条目,因此您不必使用限制 1 因为每个分区键只有一个条目......这将是 cassandra 中的常用解决方案。
如果您害怕额外的写入,请不要担心,它们很便宜并且 cpu 受限。对于 cassandra,我猜它总是 "bring on the writes" :)
基本上由您决定:
- 多个查询 - 一些重构,没有额外的 space 成本
- 新模式 - 写入时额外插入,额外 space 成本
您的 table 定义不适合 table IN 子句的此类使用。实际上,它在主键的最后一个字段或集群键的最后一个字段上受支持。所以你可以:
- 交换主键的最后两个字段
- 对每个设备 ID 使用一个查询