虚拟分区键总是坏的吗?

时间:2016-01-21 12:48:56

标签: cassandra

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

dummy  | id   | name
-------------------------
0      | 01   | 'Oliver'
0      | 02   | 'James'
0      | 03   | 'Nicholls'

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

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

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

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

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

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

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

此时我的选项已经用完了。我需要在我的表中使用一个对所有客户端都一致的字段,但是这个字段不存在,所以我现在考虑使用一个包含1-3中随机数的新字段然后进行分区在那个领域,这基本上只是一个虚拟领域。唯一的区别是我想稍微随机化这些值,以避免热点和无限的行增长。

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

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

2 个答案:

答案 0 :(得分:3)

  

我在Cassandra中找不到关于虚拟分区键的主题,但是我能找到的却倾向于支持你应该完全避免它们的想法。

我要走出困境,猜测你的搜索已经发表了我的文章We Shall Have Order!,在那里我明确地使用了“虚拟”分区键。考虑到这一点,我将尝试提供一些替代解决方案。

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

  

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

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

CREATE TABLE sites_by_id (
  id BIGINT,
  name TEXT,
  PRIMARY KEY (id));

您可以更轻松地运行Cassandra 3.0,因为您可以使用materialized view来实现此功能。

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

  

请求所有网站

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

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

答案 1 :(得分:2)

  

或要求所有网站

所以基本上你有一个全表扫描场景。对于 Cassandra ,是不是 Apache Spark 更适合这个用例?我怀疑它是一个分析用例,不是吗?

据我所知,您希望通过其ID访问单个站点,在这种情况下,通过分区键进行查找是理想的选择。另一个需要获取所有站点的用例最适合Spark