Cassandra中按分区限制查询的部分分区键

时间:2018-04-05 20:59:58

标签: cassandra

我有一个表格(让我们称之为T)设置了一个PRIMARY KEY,如下所示:

PRIMARY KEY ((A, B), C, ....);

我想查询它如下:

SELECT * FROM T WHERE A = ? and C <= ? PER PARTITION LIMIT 1 ALLOW FILTEIRNG;

(请注意,C是一个timstamp值。我基本上要求所有分区的最新行,其第一个分区键属于我的输入。)

这适用于allow过滤命令,这就是我需要它的原因;我事先不知道分区键B,我不在乎 - 我想要所有这些。因此,Cassandra需要扫描整个分区才能得到结果,这也是有道理的,为什么我需要指定它以允许对此进行过滤。

但是,我已经读过,我们应该避免“允许过滤”。不惜一切代价,因为它可以产生巨大的性能影响,特别是在生产环境中。实际上,我只在我现有的应用程序中非常谨慎地使用allow过滤,这通常用于计算这种性质的一次性查询。

我的问题是:有没有办法重构这个表或查询以避免过滤?我认为这是不可能的,因为我事先并不知道构成B的键,但我想仔细检查以确定。谢谢!

1 个答案:

答案 0 :(得分:2)

如果(A, B)是您的分区键,则无法有效地进行该查询。您的密钥需要((A), B)(丢弃群集密钥)。然后是SELECT * FROM T WHERE A = ?。如果只关心最新的,那么A,B总会被最新的替换。

如果想要从一个时间获得A,B元组,另一个选择是创建一个按时间索引的表,并使元组从那里聚类列,如((time_bucket), A, B, C)time_bucket2018-04-06:00:00:00之类的字符串,其中包含当天的所有事件。然后当您查询时:

> CREATE TABLE example (time_bucket text, A int, B int, C int, D int, PRIMARY KEY ((time_bucket), A, B, C)) WITH CLUSTERING ORDER BY (A ASC, B ASC, C DESC);

> INSERT INTO example (time_bucket, A, B, C, D) VALUES ('2018-04', 1, 1, 100, 999);
> INSERT INTO example (time_bucket, A, B, C, D) VALUES ('2018-04', 1, 1, 120, 999);
> INSERT INTO example (time_bucket, A, B, C, D) VALUES ('2018-04', 1, 1, 130, 999);
> INSERT INTO example (time_bucket, A, B, C, D) VALUES ('2018-04', 1, 2, 130, 999);

> SELECT * FROM example WHERE time_bucket = '2018-04' GROUP BY time_bucket, A, B;

 time_bucket | a | b | c   | d
-------------+---+---+-----+-----
     2018-04 | 1 | 1 | 130 | 999
     2018-04 | 1 | 2 | 130 | 999

您将从时间桶分区中的每个行获得第一个结果,其中A和B聚类。如果您使分区足够小(使用更精细的谷物时间桶,如小时或15分钟或某些东西,取决于数据速率)在这里使用ALLOW FILTERING更容易接受,如:

SELECT * FROM example WHERE time_bucket = '2018-04' AND A = 1 AND C < 120 GROUP BY time_bucket, A, B ALLOW FILTERING ;

 time_bucket | a | b | c   | d
-------------+---+---+-----+-----
     2018-04 | 1 | 1 | 100 | 999

因为它全部在一个分区内并且在有限大小内(使用tablestats / max分区大小密切监视它)。确保始终使用time_bucket查询,但它不会成为范围查询。你想确保你不会在没有返回结果的情况下经历太多事情(这是允许过滤的危险之一)。