Cassandra 数据建模少于 1000 条记录以适应一行
Cassandra data modelling less then 1000 records to fit in one row
我们有一些由生成的 UUID 唯一标识的实体。我们需要支持按名称查找查询。我们还需要支持按名称排序。
我们知道不会有超过 1000 个该类型的实体完全适合一行。硬编码主键是否可行,使用 name 作为聚类键,使用 id 作为聚类键以满足唯一性。假设我们需要学校实体。这是示例:
CREATE TABLE school (
constant text,
name text,
id uuid,
description text,
location text,
PRIMARY KEY ((constant), name, id)
);
初始状态会给我所有学校,然后会按确切名称进行过滤。我们这样做的原因是将所有学校放在单行中以便快速访问,将 name 作为聚类列用于过滤,并将 id 作为聚类列以保证唯一性。我们可以使用 constant = school
作为已知的硬编码值来访问此行。
我喜欢这个解决方案的一点是所有值都在一行中,而且我们可以快速读取。我们也可以通过聚类列轻松解决排序问题。我不喜欢的是 constant
的硬编码值,它的接缝很奇怪。我们可以使用 name
作为 PK,但是我们会有 1000 条记录分布在几个分区中,可能会发现所有没有名称的记录会更慢并且不会被排序。
问题 1
这是可行的解决方案吗?它是否存在我们没有发现的任何问题?我没有看到任何关于使用硬编码主键的 Cassandra 数据建模的示例,可能是出于这个原因,所以我们怀疑这个解决方案。
问题二
名称是可编辑的字段,它可能很少更改(有人可能会打错字或学校可以更改名称)但它可以更改。实现这一目标的最佳方法是什么? Delete insert inside batch(LTE 可以应用于带条件子句的同一行)?
是的,对于这么小的数据集,这是一个很好的方法。仅仅因为 Cassandra 可以跨多个节点对大型数据集进行分区并不意味着您需要对每个 table 使用该功能。通过为分区键使用常量,您是在告诉 Cassandra 您希望将数据存储在一个节点上,以便您可以按排序顺序快速访问数据。关系数据库一直作用于单个节点中的数据,所以这确实不是什么不寻常的事情。
为了安全起见,您可能希望使用大于 1 的复制因子,以便单个分区至少有两个副本。这样,如果存储数据的一个节点出现故障,您将不会失去对数据的访问权限。
如果您希望有很多客户端(即数千个客户端)经常读取和写入此 table,此方法可能会导致问题,因为它可能成为热点。只有 1000 条记录,您可以通过设置 table 缓存所有键和行来将所有行缓存在内存中。
您可能不会找到很多这样做的示例,因为人们转向 Cassandra 是为了支持大型数据集,他们希望通过使用多个分区获得可扩展性。所以例子是针对那个的。
Is this viable solution and are there any problems with it which we do not see? I did not see any example on Cassandra data modelling with hardcoded primary key probably for the reason so we are doubting this solution.
我在今年早些时候的文章中简要介绍了这种类型的建模解决方案:We Shall Have Order! 这就是所谓的 "dummy key,",其中每一行都具有相同的分区键。这是一个快捷方式,可让您通过聚类列轻松地对所有行(在未绑定的 SELECT *
上)进行排序。
此解决方案存在的问题:
Cassandra 允许每个分区键最多有 20 亿个列值。使用虚拟分区键时,您添加的每个值都会接近此限制。
您的数据将全部存储在同一个分区中,这将在您的集群中创建一个 "hot spot"(大数据分组)。这意味着您的数据模型将立即使 Cassandra 的主要优势之一失效……数据分布。这也会使负载平衡复杂化(相同的节点和范围将继续为您的所有请求提供服务)。
我可以看到您的模型是围绕 SELECT *
查询设计的。当您可以为 Cassandra 提供特定的查询键时,Cassandra 的效果最好。未绑定 SELECT *
查询(没有 WHERE 子句的查询)不适合使用 Cassandra,因为它们会导致超时(随着数据的增长)。
通过阅读您的问题,我知道您会说您只将它用于 1000 行。您的数据集永远不会超过这 1000 行,因此您不会遇到我提到的任何障碍。
那么我想知道,你为什么使用 Cassandra? 作为 Cassandra MVP,我不常问这个问题。但是您没有特别大的数据集(这是 Cassandra 旨在处理的数据集)。依靠这个事实作为 错误使用产品的理由 并不是最好的解决方案。
老实说,我建议您为自己省去一些复杂性,改用 RDBMS。这将比 Cassandra 更适合您的用例。然后您可以根据需要更新和订购任何字段。
我们有一些由生成的 UUID 唯一标识的实体。我们需要支持按名称查找查询。我们还需要支持按名称排序。
我们知道不会有超过 1000 个该类型的实体完全适合一行。硬编码主键是否可行,使用 name 作为聚类键,使用 id 作为聚类键以满足唯一性。假设我们需要学校实体。这是示例:
CREATE TABLE school (
constant text,
name text,
id uuid,
description text,
location text,
PRIMARY KEY ((constant), name, id)
);
初始状态会给我所有学校,然后会按确切名称进行过滤。我们这样做的原因是将所有学校放在单行中以便快速访问,将 name 作为聚类列用于过滤,并将 id 作为聚类列以保证唯一性。我们可以使用 constant = school
作为已知的硬编码值来访问此行。
我喜欢这个解决方案的一点是所有值都在一行中,而且我们可以快速读取。我们也可以通过聚类列轻松解决排序问题。我不喜欢的是 constant
的硬编码值,它的接缝很奇怪。我们可以使用 name
作为 PK,但是我们会有 1000 条记录分布在几个分区中,可能会发现所有没有名称的记录会更慢并且不会被排序。
问题 1
这是可行的解决方案吗?它是否存在我们没有发现的任何问题?我没有看到任何关于使用硬编码主键的 Cassandra 数据建模的示例,可能是出于这个原因,所以我们怀疑这个解决方案。
问题二
名称是可编辑的字段,它可能很少更改(有人可能会打错字或学校可以更改名称)但它可以更改。实现这一目标的最佳方法是什么? Delete insert inside batch(LTE 可以应用于带条件子句的同一行)?
是的,对于这么小的数据集,这是一个很好的方法。仅仅因为 Cassandra 可以跨多个节点对大型数据集进行分区并不意味着您需要对每个 table 使用该功能。通过为分区键使用常量,您是在告诉 Cassandra 您希望将数据存储在一个节点上,以便您可以按排序顺序快速访问数据。关系数据库一直作用于单个节点中的数据,所以这确实不是什么不寻常的事情。
为了安全起见,您可能希望使用大于 1 的复制因子,以便单个分区至少有两个副本。这样,如果存储数据的一个节点出现故障,您将不会失去对数据的访问权限。
如果您希望有很多客户端(即数千个客户端)经常读取和写入此 table,此方法可能会导致问题,因为它可能成为热点。只有 1000 条记录,您可以通过设置 table 缓存所有键和行来将所有行缓存在内存中。
您可能不会找到很多这样做的示例,因为人们转向 Cassandra 是为了支持大型数据集,他们希望通过使用多个分区获得可扩展性。所以例子是针对那个的。
Is this viable solution and are there any problems with it which we do not see? I did not see any example on Cassandra data modelling with hardcoded primary key probably for the reason so we are doubting this solution.
我在今年早些时候的文章中简要介绍了这种类型的建模解决方案:We Shall Have Order! 这就是所谓的 "dummy key,",其中每一行都具有相同的分区键。这是一个快捷方式,可让您通过聚类列轻松地对所有行(在未绑定的 SELECT *
上)进行排序。
此解决方案存在的问题:
Cassandra 允许每个分区键最多有 20 亿个列值。使用虚拟分区键时,您添加的每个值都会接近此限制。
您的数据将全部存储在同一个分区中,这将在您的集群中创建一个 "hot spot"(大数据分组)。这意味着您的数据模型将立即使 Cassandra 的主要优势之一失效……数据分布。这也会使负载平衡复杂化(相同的节点和范围将继续为您的所有请求提供服务)。
我可以看到您的模型是围绕
SELECT *
查询设计的。当您可以为 Cassandra 提供特定的查询键时,Cassandra 的效果最好。未绑定SELECT *
查询(没有 WHERE 子句的查询)不适合使用 Cassandra,因为它们会导致超时(随着数据的增长)。
通过阅读您的问题,我知道您会说您只将它用于 1000 行。您的数据集永远不会超过这 1000 行,因此您不会遇到我提到的任何障碍。
那么我想知道,你为什么使用 Cassandra? 作为 Cassandra MVP,我不常问这个问题。但是您没有特别大的数据集(这是 Cassandra 旨在处理的数据集)。依靠这个事实作为 错误使用产品的理由 并不是最好的解决方案。
老实说,我建议您为自己省去一些复杂性,改用 RDBMS。这将比 Cassandra 更适合您的用例。然后您可以根据需要更新和订购任何字段。