【问题标题】:Are dummy partition keys always bad?虚拟分区键总是坏的吗?
【发布时间】:2021-09-03 22:24:13
【问题描述】:

我在 Cassandra 中找不到太多关于虚拟分区键的主题,但我能找到的内容倾向于您应该完全避免使用它们的想法。通过虚拟,我的意思是一个列,其唯一目的是为所有行包含相同的值,从而将所有数据放在一个节点上并提供尽可能低的基数。例如:

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

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

1) 您最终会得到数据“热点”。 1 个节点上存储了大量数据,因此该节点周围的流量较多,并且您在集群周围的分布很差。

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

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

这让我陷入了尴尬的境地,因为该表要么在任何内容或站点 ID 上都被查询,而将唯一字段设置为分区键会给我在请求所有站点的查询时提供非常高的基数和高延迟.

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

我可以在 x 列上对我的数据进行分区,但我们有许多客户,他们都以不同的方式使用我们的系统,所以 x 为 1 个客户可能会给出我想要的结果,但可能会给另一个客户带来糟糕的结果。

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

我知道这是一个数据建模问题,它因系统而异,当然在某些情况下您必须选择两害相权取其轻(没有完美的解决方案),但我我真正关注的问题是:

在 Cassandra 中,虚拟分区键是完全不应该考虑的,还是在某些情况下可以接受?如果您认为是前者,那么您将如何处理这种情况?

【问题讨论】:

    标签: cassandra


    【解决方案1】:

    我在 Cassandra 中找不到太多关于虚拟分区键的信息,但我能找到的内容倾向于你应该完全避免使用它们的想法。

    我会冒昧地猜测你的搜索已经产生了我的文章We Shall Have Order!,我在其中非常清楚地表明了我对使用“虚拟”分区键的立场。考虑到这一点,我将尝试提供一些替代解决方案。

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

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

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

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

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

    请求所有网站

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

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

    【讨论】:

      【解决方案2】:

      或请求所有网站

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

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

      【讨论】:

        猜你喜欢
        • 2016-07-08
        • 1970-01-01
        • 1970-01-01
        • 2011-05-12
        • 2015-04-05
        • 2018-08-28
        • 2019-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多