我正在尝试将SQL中一个相对常见的需求转换为Cassandra中的高效数据模型。我正试图决定如何最好地建模我的数据,这样我就可以按照我希望在应用程序中报告的顺序,在Cassandra中排序我的行。通常,对于集群列来说,这将是一个很好的例子,但我希望对结果排序的数据是每天更新几次的度量。
我将解释SQL中的问题,然后分享我遇到的数据建模方法。我想知道的是,是否有人面临类似的要求来挖掘,如果有的话,你是如何在Cassandra中对数据建模的。
这就是我想解决的问题。
假设我有一个定义如下的raw_data表:
CREATE TABLE raw_data (
A varchar,
B varchar,
C varchar,
D varchar,
ts timestamp,
val varint
PRIMARY KEY (ts,A,B,C,D)
);我还有一张汇总表
CREATE TABLE summary_table (
A varchar,
B varchar,
C varchar,
total_val varint
PRIMARY KEY (A,B,C)
);其中,我的汇总表中的数据是由我的应用程序以一种对应于
SELECT A, B, C, SUM(val) FROM raw_data GROUP BY A, B, C我想要做的是执行如下查询:
SELECT B, C, total_val FROM summary_table WHERE A = "Something" ORDER BY total_val DESC LIMIT 1000;也就是说,我想对特定值A的汇总表进行子集,然后返回由total_val排序的前1000行
Total_val每隔几分钟由我的应用程序更新一次,因为附加数据被流到我的raw_data表中。因此,我不能将total_val用作数据的群集列
我想要决定的是如何最好地在Cassandra中建模这种类型的问题--在这个问题中,我需要用WHERE子句对汇总表进行子集,并按DESC顺序排序结果集(不断更新)。
其中一些结果集可能相当大--数十万行(也就是说,我的汇总表中有一些SELECT COUNT(*) FROM summary_table WHERE A = "some value"非常非常大,以几十万行为单位的值)。在发送到我的应用程序之前,对这些数据进行排序和丢弃显然是效率低下的。
此外,这似乎不是二级索引的一个很好的用例。在较小的结果集上,它们具有很强的性能。对于较大的国家,他们是滞后的,我怀疑可能有更好的方法来处理这个问题。
我考虑过的另一种建模方法是将更大的结果集缓存到内存中,以便至少在需要对数千行进行排序的地方,至少在内存中这样做。我还考虑过有一个备用汇总表,它已经预先填充了我想要公开给我的应用程序的前1000行.虽然我想不出一个好的方法来保持这些数据的最新,并避免与我原来的汇总表完全相同的问题。
是否有人遇到过这样的问题:您需要使用WHERE子句过滤汇总数据,并为您的(经常更改的)排序,结果是Desc顺序?如果是这样的话,当确定WHERE子句将返回数千行时,您是否找到了一种方法来使此执行语句?如果是的话,你是怎么做的?
发布于 2014-09-16 20:10:03
我认为最好的方法是这样做:
CREATE TABLE summary_table (
time_bucket long,
A varchar,
total_val int,
timestamp long,
B varchar,
C varchar,
PRIMARY KEY ((time_bucket, A), total_val, timestamp, B, C)
) WITH CLUSTERING ORDER BY (total_val DESC);使用这种结构,您实际上不会覆盖total_val。相反,为每个新值插入一个新行,然后在查询时丢弃除最新时间戳之外的所有时间戳。time_bucket的值应该是您的时间戳,舍入到您可以在查询时计算的时间间隔(您可能必须一次查询多个桶,但如果可能的话,请尝试将它限制为两个)。如果您想知道,time_bucket和A将成为您的分区键,这将阻止无界行随时间的增长。
换句话说,您已经将您的汇总表转换为时间序列数据。如果需要的话,您可以向旧列添加一个TTL,这样它们就自然死掉了。只要你的时间桶是理智的,你就不会遇到查询大量墓碑的问题。
https://stackoverflow.com/questions/25872900
复制相似问题