我们有一些由生成的 UUID 唯一标识的实体。我们需要支持按名称查找查询。此外,我们还需要支持按名称排序。
我们知道,能够完美放入一行的该类型实体不会超过 1000 个。硬编码主键是否可行,使用 name 作为集群键,使用 id 作为集群键来满足唯一性。假设我们需要学校实体。这是示例:
CREATE TABLE school (
constant text,
name text,
id uuid,
description text,
location text,
PRIMARY KEY ((constant), name, id)
);
初始状态将为我提供所有学校,然后将按确切名称进行过滤。我们这样做的原因是将所有学校放在单行中以便快速访问,将名称作为用于过滤的聚类列,并将 id 作为聚类列以保证唯一性。我们可以使用 constant = school
作为已知的硬编码值来访问该行。
我喜欢这个解决方案的一点是,所有值都在一行中,并且我们可以快速读取。我们还可以通过对列进行聚类来轻松解决排序问题。我不喜欢的是 constant
的硬编码值,这看起来很奇怪。我们可以使用 name
作为 PK,但是这样我们就会有 1000 条记录分布在几个分区中,可能会发现所有没有 name 的记录会更慢并且不会被排序。
问题1
这是可行的解决方案吗?它是否存在我们没有看到的问题?我没有看到任何关于带有硬编码主键的 Cassandra 数据建模的示例,可能是因为这个原因,所以我们怀疑这个解决方案。
问题2
名称是可编辑字段,可能很少更改(有人可能会打错字或学校可以更改名称),但它可以更改。实现这一目标的最佳方法是什么?删除批处理内的插入(LTE 可以通过条件子句应用于同一行)?
最佳答案
是的,对于如此小的数据集来说,这是一个很好的方法。仅仅因为 Cassandra 可以跨多个节点对大型数据集进行分区,并不意味着您需要对每个表使用该功能。通过使用分区键常量,您可以告诉 Cassandra 您希望将数据存储在一个节点上,以便您可以按排序顺序快速访问数据。关系数据库始终作用于单个节点中的数据,因此这确实不是一件不寻常的事情。
为了安全起见,您可能需要使用高于 1 的复制因子,以便单个分区至少有两个副本。这样,即使存储数据的一个节点出现故障,您也不会失去对数据的访问。
如果您预计有很多客户端(即数千个客户端)频繁读取和写入此表,则此方法可能会导致问题,因为它可能会成为热点。如果只有 1000 条记录,您可以通过将表设置为缓存所有键和行来将所有行缓存在内存中。
您可能找不到很多这样做的示例,因为人们转向 Cassandra 以支持大型数据集,他们希望通过使用多个分区来获得可扩展性。因此示例就是针对这一点的。
关于Cassandra 数据建模 一行中少于 1000 条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32301013/