【问题标题】:Cassandra for time series data: how to size the partition?Cassandra 用于时间序列数据:如何调整分区大小?
【发布时间】:2018-02-08 00:44:01
【问题描述】:

我正在尝试使用 Cassandra 存储来自某些传感器的数据。 我阅读了很多关于 Cassandra 时间序列数据模型的文章。我从Getting Started with Time Series Data Modeling 开始,“时间序列模式 2”看起来是最好的方法。 所以我创建了一个复制因子为 2 的键空间和一个像这样的表

CREATE TABLE sensors_radio.draw (
dvid uuid,
bucket_time date,
utc_time double,
fft_size int,
n_avg int,
n_blocks int,
power double,
sample_rate double,
start_freq double,
PRIMARY KEY ((dvid, bucket_time), utc_time)

dvid 是唯一的设备 ID,bucket_time 是一天(例如 2017-08-30),utc_time 是时间戳。

我的查询是

SELECT utc_time,start_freq,sample_rate,fft_size,n_avg,n_blocks,power
FROM sensors_radio.draw 
WHERE dvid=<dvid> 
AND bucket_time IN (<list-of-days>) 
AND utc_time>=1.4988002E9 
AND utc_time<1.4988734E9;

如您所见,我需要检索多天的数据,这意味着读取集群中的多个分区。在我看来,查询性能看起来很差,由于 IN 反模式,这是可以理解的。

编辑:我试图通过将查询拆分为多个来避免 IN 反模式,但我没有得到任何性能提升。

我考虑通过使用 month 而不是 day 作为 bucket_time 来增加我的分区大小,以使用我的查询来查询单个分区。 但我担心分区会增长太多!通过阅读this question 的答案,我发现在一个月内我的分区将拥有大约 5 亿个单元(远低于 20 亿个限制),但它当然会超过 100MB 大小限制和 100000 行限制。

在这种情况下推荐的数据模型是什么?大磁盘分区是个问题吗?

提前致谢。

附言。我在由 3 个节点(8 核,16GB 内存)组成的集群上使用 Cassandra 3.10

【问题讨论】:

  • IN 实际上是一种反模式,因为多分区查询通常“太慢”。此外,磁盘上的大分区还会导致压缩和读取性能出现其他一些问题。
  • 我强烈建议从 3.2 迁移到 3.11,尤其是 3.9 之前的版本有很多问题。
  • 对不起,我的错误。我正在使用 Cassandra 3.10。如果我更新到 3.11,我会丢失数据吗?
  • 升级 cassandra 是相当安全的 - 留意你的配置。阅读您对新 cassandra.yaml 的所有更改并查找 nodetool upgradesstables(请参阅 docs.datastax.com/en/cassandra/3.0/cassandra/tools/…

标签: cassandra time-series


【解决方案1】:

正如您所说,使用 IN 的查询可能会很慢,因为在您的情况下需要读取多个分区,但您的查询是从一个协调节点处理的(如果可能,通常选择该节点作为负责分区的节点) .

此外,大分区在过去一直是一场噩梦 - 在 3.6 及更高版本中,它应该不会那么糟糕(参见 https://de.slideshare.net/DataStax/myths-of-big-partitions-robert-stupp-datastax-cassandra-summit-2016)。读取性能和内存压力一直是严重的问题。

什么对我来说非常有效 - 但取决于您的用例 - 使用“足够小”的存储桶(天)并在一个月内异步并行发出 31 个查询,然后将它们重新加入您的代码中。例如,在 java 中有期货支持你。这样,每个查询只会命中一个存储桶/分区,并且集群中的所有节点很可能会并行处理您的查询。

【讨论】:

  • 嗨@Mandraenke,感谢您的回答。您将查询拆分为多个查询是正确的。这是我在阅读this 后已经完成的工作,但是我没有性能提升(执行时间完全相同)。我没有提到它,因为我的问题会变得太复杂。我现在要更新它。
  • 你是异步执行的吗?
  • 是的,如链接中的文章所述。
  • 我试过这个:我从 Java 中执行了一个查询,它分为 4 个,异步的,带有期货。检索所有 2812033 行大约需要 40 秒。你觉得那段时间怎么样?合理吗?
  • 这大约是每秒 70k 行 - 如果可以,这不取决于行大小 - 监控您的网络带宽并加载您的集群节点和发出查询的服务器上的带宽。需要指出的是 - 在您的 4 个查询中还有 IN 吗?
【解决方案2】:

其实你对列值大小的含义理解错了。

限制大约 20 亿 - 这与行数无关,而是常规列和集群键的工作方式

Nv=Nr(Nc−Npk−Ns)+Ns使用这个公式

分区中的值(或单元格)数 (Nv) 等于静态列数 (Ns) 加上行数 (Nr) 与每行值数的乘积。每行的值数定义为列数 (Nc) 减去主键列数 (Npk) 和静态列数 (Ns)。

简短描述为number of rows multiply by number of regular columns

你的情况是:

(500 000 000 * (9 - 3 - 0) + 0) = 3 000 000 000

所以你超出了限制20亿

计算磁盘大小的公式

而且你在磁盘上的分区大小会很大

(20 + 0 + (500000000 * 84) + (8 * 3000000000)) = 
66000000020 bytes (62942.50 Mb)

显然超过 100 Mb cassandra 限制

我使用我的开源项目 - cql-calculator 计算得出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 2013-01-25
    • 2019-10-17
    • 2017-01-19
    • 1970-01-01
    • 2011-01-13
    • 2021-07-29
    相关资源
    最近更新 更多