【问题标题】:Is Leveled Compaction Strategy still beneficial for reads when Rows Are Write-Once?当行是一次写入时,分级压缩策略是否仍然有利于读取?
【发布时间】:2018-03-30 14:10:46
【问题描述】:

在其他情况下,datastax post 表示当行是一次性写入时,压缩可能不是一个好的选择

如果您的行总是一次全部写入并且从不更新,那么在使用大小分层压缩时,它们自然会始终包含在单个 SSTable 中。因此,水平压实实际上并没有什么好处。

另外,在谈话 The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla) 第 30 张幻灯片中,它说 LCS 最适合的地方

需要非常一致的读取性能和更高读写比的用例

总分区数有限(或增长缓慢)但更新和删除很多的宽分区数据模型,或完全 TTL 的数据集

我了解如果频繁更新或删除一行,它可能会出现在多个 SSTable 中,因此这会影响读取性能。来自Leveled Compaction in Apache Cassandra

性能可能不一致,因为无法保证一行可以分布在多少个 sstable 中:在最坏的情况下,我们可以在每个 sstable 中包含来自给定行的列。

但是,在 Rows Are Write-Once 的场景中,此策略在读取分区键的所有行时也不能代表好处?

因为如果我理解正确,使用这种策略,具有相同分区键的行往往位于同一个 SSTable 中,因为合并重叠的 SSTable 与合并具有相似大小的 SSTable 的 Size Tiered Compaction 形成对比。

【问题讨论】:

    标签: cassandra datastax


    【解决方案1】:

    当行严格写入一次时,选择 LeveledCompactionStrategy 而不是 SizeTieredCompactionStrategy 对读取性能没有影响(还有其他影响,例如 LCS 需要更多 IO)

    关于以下问题的cmets

    使用这种策略,具有相同分区键的行往往在 相同的 SSTable,因为合并了重叠的 SSTable 合并大小相似的 SSTables 的 Size Tiered Compaction。

    当具有相同分区键的行只写入一次时,就没有合并 SSTables 的场景,因为它首先不会分散在不同的 SSTables 中。

    当我们谈论更新时,它不一定是要更新的行中的现有列。在某些情况下,我们添加一组完整的新集群列以及现有分区键的关联列。

    这是一个示例表

    CREATE TABLE tablename(
       emailid text,
       sent-date date,
       column3 text,
       PRIMARY KEY (emailid,sent-date)
       )
    

    现在,对于给定的电子邮件 ID(比如 hello@gmail.com),单个分区键可能会在两次或多次插入时使用不同的“发送日期”。尽管它们是对相同分区键的插入(本质上是 upsert),因此 LeveledCompaction 将在这里受益。

    但是假设同一个表只使用 emailid 作为主键并且只写一次。那么无论 SSTable 是如何压缩的,无论是 SizeTieredCompactionStrategy 还是 LeveledCompactionStrategy,都没有优势,因为行总是只存在于一个 SSTable 上。

    【讨论】:

    • 当分区键是主键并且行被写入一次时,LCS在读取性能方面没有任何好处,这一点很明显。我的问题是关于使用相同分区键写入一次的多行。对于您所说的:“尽管它们是对同一分区键的插入(本质上是 upsert),因此 LevelTieredCompaction 将在这里受益”,我理解您同意我的观点,即 LCS 在这种情况下代表了一种好处,关于这是行被写入一次的场景。
    • @santiagomaldonado 如果没有进一步的说明,请您接受答案
    • 对于更大的数据集,使用 LCS 读取几乎总是更快,即使写入一次也是如此。随着 STCS 增长超过 200 亿个左右的分区,检查布隆过滤器和较大 sstables 的索引摘要的成本很高,这必须在每次读取时发生(密钥缓存有很大帮助)。通常,您还必须检查所有 sstables,因为 min/max 令牌通常分布在整个范围内。由于 LCS 按每个级别的令牌范围拆分 sstable,因此它保证您只需检查每个级别的 1 个小型 sstable(可能的异常 L0)。如果使用 SSD,我实际上总是建议默认使用 LCS。
    • @ChrisLohfink 这将是 LCS 压缩的大量 I/O,因此开销会蔓延到延迟时间的增加
    • @Jubobs 是的,我的意思是 LeveledCompaction,会修正错字。
    【解决方案2】:

    我认为响应是当博客谈论一行时,它指的是 Thrift 行而不是 CQL 行。 (我是 not the only 来混淆这个术语)

    当我们说 Thrift 行时,我们指的是一个分区(或一组具有相同分区键的 CQL 行)。 来自Does CQL support dynamic columns / wide rows?

    +--------------------------------------------------+-----------+
    |                   Thrift term                    | CQL term  |
    +--------------------------------------------------+-----------+
    | row                                              | partition |
    | column                                           | cell      |
    | [cell name component or value]                   | column    |
    | [group of cells with shared component prefixes]  | row       |
    +--------------------------------------------------+-----------+
    

    来自Understanding How CQL3 Maps to Cassandra’s Internal Data Structure 使用以下架构

    CREATE TABLE tweets (
            ... user text,
            ... time timestamp,
            ... tweet text,
            ... lat float,
            ... long float,
            ... PRIMARY KEY (user, time)
            ... );
    

    (请记住,分区键是第一个出现在主键中的,在本例中为“用户”)

    以下 CQL 行

    user         | time                     | lat    | long    | tweet
    --------------+--------------------------+--------+---------+---------------------
     softwaredoug | 2013-07-13 08:21:54-0400 | 38.162 | -78.549 |  Having chest pain.
     softwaredoug | 2013-07-21 12:15:27-0400 | 38.093 | -78.573 |   Speedo self shot.
          jnbrymn | 2013-06-29 20:53:15-0400 | 38.092 | -78.453 | I like programming.
          jnbrymn | 2013-07-14 22:55:45-0400 | 38.073 | -78.659 |     Who likes cats?
          jnbrymn | 2013-07-24 06:23:54-0400 | 38.073 | -78.647 |  My coffee is cold.
    

    像这样在 Thrift 内部持久化

    RowKey: softwaredoug
    => (column=2013-07-13 08:21:54-0400:, value=, timestamp=1374673155373000)
    => (column=2013-07-13 08:21:54-0400:lat, value=4218a5e3, timestamp=1374673155373000)
    => (column=2013-07-13 08:21:54-0400:long, value=c29d1917, timestamp=1374673155373000)
    => (column=2013-07-13 08:21:54-0400:tweet, value=486176696e67206368657374207061696e2e, timestamp=1374673155373000)
    => (column=2013-07-21 12:15:27-0400:, value=, timestamp=1374673155407000)
    => (column=2013-07-21 12:15:27-0400:lat, value=42185f3b, timestamp=1374673155407000)
    => (column=2013-07-21 12:15:27-0400:long, value=c29d2560, timestamp=1374673155407000)
    => (column=2013-07-21 12:15:27-0400:tweet, value=53706565646f2073656c662073686f742e, timestamp=1374673155407000)
    -------------------
    RowKey: jnbrymn
    => (column=2013-06-29 20:53:15-0400:, value=, timestamp=1374673155419000)
    => (column=2013-06-29 20:53:15-0400:lat, value=42185e35, timestamp=1374673155419000)
    => (column=2013-06-29 20:53:15-0400:long, value=c29ce7f0, timestamp=1374673155419000)
    => (column=2013-06-29 20:53:15-0400:tweet, value=49206c696b652070726f6772616d6d696e672e, timestamp=1374673155419000)
    => (column=2013-07-14 22:55:45-0400:, value=, timestamp=1374673155434000)
    => (column=2013-07-14 22:55:45-0400:lat, value=42184ac1, timestamp=1374673155434000)
    => (column=2013-07-14 22:55:45-0400:long, value=c29d5168, timestamp=1374673155434000)
    => (column=2013-07-14 22:55:45-0400:tweet, value=57686f206c696b657320636174733f, timestamp=1374673155434000)
    => (column=2013-07-24 06:23:54-0400:, value=, timestamp=1374673155485000)
    => (column=2013-07-24 06:23:54-0400:lat, value=42184ac1, timestamp=1374673155485000)
    => (column=2013-07-24 06:23:54-0400:long, value=c29d4b44, timestamp=1374673155485000)
    => (column=2013-07-24 06:23:54-0400:tweet, value=4d7920636f6666656520697320636f6c642e, timestamp=1374673155485000)
    

    我们清楚地看到,用户 softwaredoug 的 2 个 CQL 行是一个 Thrift Row。

    单个 CQL 行对应单个 Thrift 行的情况(例如,当分区键 == 主键时)是 Deng 和 Svihla 表示的 an anti-pattern use case for LCS

    所有唯一分区的大量写入

    但是,我会将 dilsingi 的答案标记为正确,因为我认为他已经知道这种关系。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-01
      • 1970-01-01
      • 2016-04-21
      • 2015-06-30
      • 2016-11-30
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多