虚拟分区键总是坏的吗?

Oli*_*lls 5 cassandra

我在Cassandra中找不到关于虚拟分区键的主题,但是我能找到的东西倾向于支持你应该完全避免它们的想法.虚拟,我指的是一个列,其唯一目的是为所有行包含相同的值,从而将所有数据放在1个节点上并给出最低的基数.例如:

dummy  | id   | name
-------------------------
0      | 01   | 'Oliver'
0      | 02   | 'James'
0      | 03   | 'Nicholls'
Run Code Online (Sandbox Code Playgroud)

关于为什么要避免虚拟分区键的两个要点是:

1)你最终得到数据"热点".在一个节点上存储了大量数据,因此该节点周围的流量较多,并且群集周围的分布较差.

2)分区空间是有限的.如果将所有数据放在一个分区上,它最终将无法存储更多数据.

我可以理解这些观点并且我同意你肯定想避免这些情况,所以我把这个想法放在我的脑海里,试着为我的桌子想一个好的分区键.有问题的表存储了站点,在我们的系统中有两种常见的表查询方式.要求单个站点或请求所有站点.

这让我处于一种尴尬的境地,因为无论是在什么都没有查询表或者站点ID,并且使得一个唯一字段,分区键会给我非常高的基数和高请求所有站点的查询延迟.

所以我决定我只选择一个会提供相对较低基数的任意字段,即使它没有反映实际查询数据的方式,只是因为它比基数过高或过低都要好. .这种方法也存在问题.

我可以在列x上对数据进行分区,但是我们有很多客户端,所有客户端都使用我们的系统,所以x for 1客户端可以给出我之后的结果,但是可能会给另一个客户端带来可怕的结果.

在这一点上,我已经没有选择了.我需要在我的表中的一个字段对所有客户端都是一致的,但是这个字段不存在,所以我现在正在考虑有一个新字段,它将包含1-3中的随机数,然后在该字段上进行分区,这基本上只是一个虚拟场.唯一的区别是我想稍微随机化这些值,以避免热点和无限的行增长.

我知道这是一个数据建模问题,它因系统而异,当然还有一些情况,你必须选择两个邪恶中较小的一个(没有完美的解决方案),但我真的是专注于这个问题的是:

虚拟分区键是否应该在Cassandra中完全不考虑,或者是否存在被认为可接受的情况?如果你认为前者,那你将如何处理这种情况?

Aar*_*ron 3

我在 Cassandra 中找不到太多关于虚拟分区键的主题,但我能找到的内容往往倾向于您应该完全避免它们的想法。

我将冒险猜测您的搜索已经找到了我的文章《我们将有秩序!》,我在其中非常明确地表达了我对使用“虚拟”分区键的立场。考虑到这一点,我将尝试提供一些替代解决方案。

我认为这里有两个潜在的问题需要解决。首先:

我的表中需要一个对于所有客户端都一致的字段,但是该字段不存在

通常,这可以通过将数据复制到另一个查询表中来解决。这是提供多种不同查询模式的最佳方式。如果您有一个客户端(服务?)需要通过站点 ID 查询该表,那么您可以将该表复制到名为 的表中sites_by_id

CREATE TABLE sites_by_id (
  id BIGINT,
  name TEXT,
  PRIMARY KEY (id));
Run Code Online (Sandbox Code Playgroud)

另一个问题是这个查询模式:

所有站点均已请求

另一个常见的 Cassandra 反模式是未绑定 SELECT(不带 WHERE 子句的 SELECT 查询)。我确信您明白为什么这些不好,因为它们需要读取所有节点/分区才能完成(这可能就是您正在研究“虚拟”密钥的原因)。但随着支持这些类型查询的表的大小增加,它们只会随着时间的推移变得越来越慢......无论您是执行未绑定的 SELECT 还是使用“虚拟”键。

这里的解决方案是重新检查您的数据模型和业务需求。也许您的数据可以按地区或国家划分到站点?也许您的客户真的只需要今年已更新的网站?获取有关客户端查询要求的更多详细信息可能会帮助您找到适合他们使用的良好分区键。否则,如果他们确实一直需要所有这些,那么 doanduyhai 使用 Spark 的建议将更适合您的用例。