当行是一次写入时,Leveled Compaction策略是否仍然有益于读取?

时间:2017-10-18 16:10:14

标签: cassandra datastax

在其他情况下,此datastax post表示 压缩可能不是行写入时的好选项

  

如果您的行总是一次完全写入并且永远不会更新,那么在使用大小分层压缩时,它们自然总是由单个SSTable包含。因此,从平整的压实中无法获得任何好处。

此外,在谈话The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla)幻灯片30中,它表示 LCS最适合

  

需要非常一致的读取性能且具有更高读写比率的用例

     

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

据我所知,如果频繁更新或删除某行,它最终会出现在多个SSTable中,因此这会影响读取性能。来自Leveled Compaction in Apache Cassandra

  

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

但是,在行是一次写入的情况下,当读取分区键的所有行时,此策略也不会带来好处吗?

因为如果我理解正确,使用此策略时,具有相同分区键的行往往位于相同的SSTable中,因为合并与大小分层压缩重叠的SSTables会合并具有相似大小的SSTable。

2 个答案:

答案 0 :(得分:2)

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

关于以下来自问题的评论

  使用此策略的

具有相同分区键的行往往是在   相同的SSTable,因为合并了与之重叠的SSTables   大小分层压缩,用于合并具有相似大小的SSTable。

当具有相同分区键的行只写入一次时,则没有合并SSTable的情况,因为它首先不会分布在不同的SSTable上。

当我们谈论更新时,它不必是该行中正在更新的现有列。可能存在这样的情况:我们添加了一组完整的新聚类列以及已存在的分区键的关联列。

这是一个示例表

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

现在对于给定的emailid(比如hello@gmail.com)一个分区密钥,可能会有两次或多次插入不同的“发送日期”。虽然它们是插入(基本上是upserts)到同一个分区键,因此LeveledCompaction在这里会受益。

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

答案 1 :(得分:1)

我认为回应是当博客谈论一行时,它指的是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)
        ... );

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

以下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)

我们清楚地看到带有用户软件的2个CQL行是一个Thrift Row。

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

  

使用所有唯一分区重写

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