【问题标题】:Is it a bad practice to have a Cassandra table with partitions of a single row?拥有一个带有单行分区的 Cassandra 表是一种不好的做法吗?
【发布时间】:2021-01-09 20:45:29
【问题描述】:

假设我有一张这样的桌子

CREATE TABLE request(
  transaction_id text,
  request_date timestamp,
  data text, 
  PRIMARY KEY (transaction_id)
);

transaction_id 是唯一的,据我了解此表中的每个分区只有一行,我不确定这种情况是否会导致操作系统出现性能问题,可能是因为Cassandra 为每个分区创建一个文件,导致为其托管操作系统管理大量文件,作为说明,我不确定 Cassandra 如何为其表创建文件。

在这种情况下,我可以通过它的 transaction_id 找到一个请求,例如

select data from request where transaction_id = 'abc';

如果前面的假设是正确的,那么下一个可能是另一种方法吗?

CREATE TABLE request( 
  the_date date, 
  transaction_id text, 
  request_date timestamp, 
  data text, 
  PRIMARY KEY ((the_date), transaction_id)
);

字段 the_date 会每隔一天更改一次,因此表中的分区将每天创建。

在这种情况下,我必须让 the_date 数据对客户端始终可用,以便我可以使用下一个查询找到请求

select data from request where the_date = '2020-09-23' and transaction_id = 'abc';

提前感谢您的热心帮助!

【问题讨论】:

    标签: cassandra primary-key partition


    【解决方案1】:

    Cassandra 不会为每个分区创建单独的文件。一个 SSTable 文件可能包含多个分区。仅包含一行的分区通常称为“瘦行” - 它们不是很糟糕,但可能会导致一些性能问题:

    • 要访问此类分区,您仍然需要读取一个包含压缩数据(默认为 64Kb)的块,该块需要解压缩才能读取该数据。如果您正在执行真正的随机访问,则此类块将从文件缓存中丢弃,并且需要从磁盘重新读取。在这种情况下,减小块大小可能很有用
    • 如果每个节点的每个表有很多这样的分区 - 这可能会大大增加布隆过滤器的大小,因为每个分区都有一个单独的条目。我看到一些客户只因为分区太窄而为布隆过滤器分配了数十 GB 的内存

    所以这实际上取决于数据量、访问模式等。它可能是好是坏,取决于这些因素。

    如果您有可用的日期,并且想将其用作部分分区键 - 这可能也不可取,因为如果您在当天写入和读取大量数据,那么只有一些节点会处理该负载 - 这就是所谓的“热分区”。

    当您从数据中推断分区键时,您可以实现所谓的分桶。但这将取决于可用的数据。例如,如果您将日期 + 交易 ID 作为字符串,则可以将分区键创建为日期 + 该字符串的第一个字符 - 在这种情况下,您每天将有 N 个分区键,它们分布在节点之间,消除了热点分区问题。

    请参阅corresponding best practices doc from DataStax 了解该主题。

    【讨论】:

    • 感谢@Alex Ott 提供的所有反馈,它非常有帮助,还提供了链接。我将更多地分析我的用例来决定是否使用瘦行方法,或者考虑避免您提到的热分区问题,是否最好用另一个字段来补充分区键,
    【解决方案2】:

    让我不要讨论不同类型的键,但让我提一下并简要解释一下您在问题中使用的两个键。

    主键

    一行必须有一个唯一的主键(将行标识为关于相等性的行)。主键可以是列的集合(如在您的第二个示例中使用(the_date), transaction_id)或只是一个列(如在您的第一个示例中使用transaction_id)。然而,如上所述,重要的部分是对于一行,主键必须是唯一的以标识该行。

    分区键

    分区键实际上是根据主键确定的。您可以拥有复合分区键(您在第二个示例中使用了该语法,以强制 (the_date) 作为分区键,这实际上不是必需的,因为默认情况下它将是主键的第一列)。

    Cassandra 使用(组合的)分区键值的散列值来确定数据存储在哪个节点上(或在请求数据时从哪个节点检索)。

    所以你的问题的答案是,使用transaction_id 作为主键和分区键是完全可以的。这不是坏习惯,如果您的数据中有一个唯一标识符,可以存储在一行中并满足您对请求的需求,这或多或少是相当普遍的做法。

    更多信息:

    【讨论】:

    • 感谢@Philipp 详细说明您的回复。我知道,鉴于主键仅包含一列,在这种情况下 transaction_id,这个唯一字段也是主键和分区键,因此该表中的每个分区将仅包含一行,我主要关心的是如果这是对 Cassandra 和/或托管操作系统的性能损失,可能是为了处理多个文件或其他东西
    • 不,在这种情况下没有惩罚(如答案中所述)。同样,这是常见的做法和 Cassandra 系统。
    猜你喜欢
    • 2015-12-02
    • 2016-12-22
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    相关资源
    最近更新 更多