3

我正在为 Cassandra 2.1.3 上的时间序列应用程序创建数据模型。我们将为系统的每个用户保留 X 量的数据,我想知道针对此要求进行设计的最佳方法是什么。

选项1:

在分区键中使用“桶”,因此 X 周期的数据进入同一行。像这样的东西:

((id, bucket), timestamp) -> data

我可以一次删除一行,但要以维护这个存储桶概念为代价。它还限制了我可以查询的范围timestamp,可能会导致多个查询。

选项2:

将所有数据存储在同一行中。N 删除是每列。

(id, timestamp) -> data

范围查询再次变得容易。但是删除许多列后性能如何?

鉴于我们计划使用 TTL 让数据过期,这两种模型中哪一种会提供最佳性能?Option1 << Option2 的墓碑开销还是两种模型上的每列都有一个墓碑?

我尽量避免把自己埋在墓碑墓地里。

4

2 回答 2

3

我认为这完全取决于您计划为您最终选择的给定分区键拥有多少数据,您的 TTL 是什么以及您正在进行什么查询。

我通常倾向于选项#1,特别是如果你的 TTL 对于所有写入都是相同的。此外,如果您使用 LeveledCompactionStrategy 或 DataTieredCompactionStrategy,Cassandra 可以很好地将来自同一分区的数据保存在同一个 SSTable 中,这将大大提高读取性能。

如果您使用选项 #2,同一分区的数据可能会分布在多个级别(如果使用 LCS)或通常只是多个 sstable,这可能会导致您从大量 SSTable 中读取,具体取决于查询的性质. 还有一个热点问题,如果你有一个非常宽的分区,你可能会超载特定的 cassandra 节点。

#1(您提到的)的另一个好处是您可以轻松删除整个分区,这会创建一个便宜得多的墓碑标记。此外,如果您使用相同的 TTL,则该分区内的数据将几乎同时过期。

我确实同意必须进行多个查询以跨多个分区进行读取有点痛苦,因为它会将一些复杂性推向应用程序端。如果无法隐式确定给定 id 的存储桶,您可能还需要维护一个单独的表来跟踪它们。

就性能而言,您是否认为在应用程序进行查询时可能需要读取跨分区?例如,如果您要查询“最近的 1000 条记录”并且分区通常比这更宽,您可能只需要对选项 #1 进行 1 次查询。但是,如果您想进行“给我所有记录”之类的查询,选项#2 可能会更好,否则您需要对每个存储桶进行查询。

于 2015-03-16T16:20:34.727 回答
2

创建上述表后:

CREATE TABLE option1 (
                 ...   id bigint,
                 ...   bucket bigint,
                 ...   timestamp timestamp,
                 ...   data text,
                 ...   PRIMARY KEY ((id, bucket), timestamp)
                 ... ) WITH default_time_to_live=10;

CREATE TABLE option2 (
                 ...   id bigint,
                 ...   timestamp timestamp,
                 ...   data text,
                 ...   PRIMARY KEY (id, timestamp)  
                 ... ) WITH default_time_to_live=10;

我插入了一个测试行:

INSERT INTO option1 (id,bucket,timestamp,data) VALUES (1,2015,'2015-03-16 11:24:00-0500','test1');
INSERT INTO option2 (id,timestamp,data) VALUES (1,'2015-03-16 11:24:00-0500','test2');

...等了 10 秒钟,通过跟踪进行查询,我看到每张桌子的墓碑计数相同。因此,无论哪种方式,我都不应该为您担心太多。

真正的问题是,如果你认为你会达到每个分区 20 亿列的限制,那么选项 #1 是安全的。如果您有大量数据,选项 #1 可能会执行得更好(因为您将无需查看与您的 不匹配的分区bucket),但实际上在这方面任何一个都应该没问题。

tl;博士;

由于无论您选择哪个选项,性能和墓碑问题都会相似,我认为选项 #2 是更好的选项,只是因为易于查询。

于 2015-03-16T17:11:26.867 回答