过度简化数据模型,我们有以下表格:
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清除数据时,问题就来了。我们必须从存储表和所有索引表中删除条目。因此,假设我们通过例如foo删除,采取的步骤是:
- 根据适当的索引表查找 id(在本例中为storage_idx_by_foo)
- 获取bar和baz并从存储表中删除记录
- 从剩余的两个索引表中删除记录(我们有bar / baz和id)
第 3 步是因为tombstones的问题- 如果我们从剩余的两个索引表中删除数百万条记录(意味着不是通过分区),Cassandra 将创建数百万条 tombstones,这在压缩发生之前读取数据时会引起很多麻烦。
一些快速的头脑风暴表明我们可以:
- 清除过程后强制压实
- 不从这两个表中删除并处理指向代码中不存在的东西的索引条目
- ???
建议的方法是什么?我猜其他 Cassandra 用户也遇到过这个问题,但除了“你做错了 Cassandra”之外,我在网上找不到任何建议。我不认为我们可以对我们的数据进行不同的建模来避免这个问题(或者如果可以的话,我也会很感激对此的反馈)。
目前,我们倾向于选项 2,尽管我不喜欢将垃圾留在数据库中的想法。