Cassandra-获取特定时间范围内的所有数据

时间:2019-05-01 02:16:34

标签: cassandra

是否可以查询Cassandra数据库以获取特定范围的记录?

我有一个这样的表定义

CREATE TABLE domain(
domain_name text,
status int,
last_scanned_date long
PRIMARY KEY(text,last_scanned_date)
)

我的要求是获取过去24小时内未扫描的所有域。我编写了以下查询,但是由于ALLOW FILTERING

,Cassandra试图获取整个数据集,因此该查询效率不高
SELECT * FROM domain where last_scanned_date<=<last24hourstimeinmillis> ALLOW FILTERING;

然后我决定在两个查询中完成

第一个查询:

SELECT DISTINCT name from domain;

第二个查询: 使用IN运算符查询最近24小时未扫描的域

SELECT * FROM domain where 
domain_name IN('domain1','domain2') 
AND 
last_scanned_date<=<last24hourstimeinmillis> 

我的第二种方法可行,但是要先查询不同的值会带来额外的开销。

有没有比这更好的方法了?

2 个答案:

答案 0 :(得分:1)

您应该更新结构表定义。当前,您正在选择域名作为分区键,而单个Cassandra分区中的记录不能超过20亿条。

我建议您将时间用作分区键的一部分。如果您每天不会收到超过20亿个请求。尝试使用自纪元以来的天作为分区键。您可以执行复合分区键,但是它们对查询没有帮助。

查询时,您必须在查询或应用程序中使用额外的过滤器最多扫描两个分区,以过滤出不属于某个结果的结果 您指定的范围。

在完成设计之前,请仔细阅读以下概念。

https://docs.datastax.com/en/cql/3.3/cql/cql_using/useCompositePartitionKeyConcept.html

https://docs.datastax.com/en/dse-planning/doc/planning/planningPartitionSize.html

答案 1 :(得分:1)

Cassandra只能在一个分区内有效地执行范围查询。对于聚合的使用也是如此,例如DISTINCT。因此,在您的情况下,您将只需要一个分区即可包含所有数据。但这是不好的设计。

您可以尝试通过将TLD用作单独的分区键,将这个大分区拆分为较小的分区,并从每个分区并行执行访存-但这也会导致不平衡,因为某些TLD的站点将比其他TLD多。

架构的另一个问题是您将last_scanned_date作为群集列,这意味着在更新last_scanned_date时,您实际上在数据库中插入了新行-您需要明确删除先前last_scanned_date的行,否则查询last_scanned_date<=<last24hourstimeinmillis>将始终获取您已扫描的旧行。

使用Spark可以部分解决您当前设计的问题,该Spark可以通过令牌范围扫描+范围扫描对每行进行有效的全表扫描-这将仅返回给定时间范围内的数据。或者,如果您不想使用Spark,则可以在代码中执行令牌范围扫描,例如this