过度简化数据模型,我们有以下表格:
CREATE TABLE storage (
id timeuuid,
foo blob,
bar blob,
baz blob,
data blob,
PRIMARY KEY ((id))
);
CREATE TABLE storage_idx_by_foo (
foo blob,
id timeuuid,
PRIMARY KEY ((foo), id)
);
CREATE TABLE storage_idx_by_bar (
bar blob,
id timeuuid,
PRIMARY KEY ((bar), id)
);
CREATE TABLE storage_idx_by_baz (
baz blob,
id timeuuid,
PRIMARY KEY ((baz), id)
);
第一个表可以包含数亿条记录,我们使用索引表根据一些可查询参数轻松定位数据。
当我们必须清除基于 foo , bar 或 baz 的数据时,问题就出现了。我们必须从 storage 表和所有索引表中删除该条目。所以,假设我们删除了例如 foo ,采取的措施是:
步骤3是一个问题,因为墓碑 - 如果我们从剩下的两个索引表中删除数百万条记录(意思不是通过分区),Cassandra将创建数百万个墓碑,这将导致很多在压实发生之前读取数据时头痛。
一些快速的头脑风暴表明我们可以:
建议的方法是什么?我猜其他Cassandra用户也遇到过这个问题,但除了“你正在做Cassandra错误”之外我在网上找不到任何建议。我认为我们不能以不同的方式对我们的数据建模以避免这个问题(或者如果我们可以的话,我也会对这方面的反馈表示赞赏)。
目前,我们倾向于选项2,尽管我不喜欢垃圾留在数据库中的想法。
答案 0 :(得分:2)
“你可能正在做cassandra错误”!!
您有什么疑问?试图在不知道查询的情况下进行推广通常会导致Cassandra中的模型不佳。建模应该是查询驱动的。即使您不知道确切的查询,您也应该知道查询的种(即您要编入索引的内容等)。
如果您知道要在foo,bar和baz上编制索引,请考虑是否可以添加一些可用作分区键的约束。对于您概述的模式,您将遇到的一个主要问题是,如果相同的foo值(或条形值或baz值)有大量条目。虽然从理论上讲,分区可能非常大,但是分区大于几十兆或大约一百个megs会因性能而坏。因此,在进行宽行时,请考虑如何限制宽行大小。如果每个foo或bar或baz有几百到几千个条目,这将不是问题。否则,你会遇到麻烦。在这种情况下,您可能想要添加一些用于分组。例如,看看您是否可以将查询限制为“在此日期获取foo x的数据”或“获取此国家/邮政编码/等的foo x数据”。这将防止巨大的行。
手动索引的另一个问题是索引更新不是原子的,索引可能与实际数据位于不同的节点上。如果您可以将查询限制为存储桶,则架构可能如下所示:
CREATE TABLE storage (
some_bucket text,
id timeuuid,
foo blob,
bar blob,
baz blob,
data blob,
PRIMARY KEY (somebucket, id)
);
甚至您可以按原样保留存储空间并将索引设为:
CREATE TABLE storage (
bucket text,
foo blob,
bar blob,
baz blob,
data blob,
PRIMARY KEY (bucket)
);
在这两种情况下,您都会在foo,bar和baz上创建一个cassandra二级索引。这将允许您的查询。记住,当使用二级索引时,总是首先命中一个分区 - 否则它会变成一个群集范围的查询,可能会超时。在Cassandra 3.0中,一个名为全局索引的功能即将推出,旨在减少首先命中分区的需求,但在此之前,命中分区+二级索引,您的查询将快速。
现在......关于墓碑的主题。 Cassandra删除将使用墓碑。没有办法解决这个问题。任何LSM数据库都需要压缩,而且无论负载如何,逻辑删除都是cassandra实现稳定写入吞吐量(几乎)的机制。但是你可以做一些事情。如果您可以限制何时发生大量删除,您可以使用nodetool来禁用自动压缩:
http://www.datastax.com/documentation/cassandra/2.1/cassandra/tools/toolsDisableAutoCompaction.html
然后,您可以执行清除,然后强制执行压缩:
http://www.datastax.com/documentation/cassandra/2.1/cassandra/tools/toolsCompact.html
再次启用自动压缩。
这显然不是“整洁”,但是如果您从表中删除了大量数据,而不是全部数据,则会有效。
希望有所帮助。