【问题标题】:Cassandra partition key for time series data时间序列数据的 Cassandra 分区键
【发布时间】:2016-07-03 02:22:54
【问题描述】:

我正在测试 Cassandra 作为时间序列数据库。

我创建数据模型如下:

CREATE KEYSPACE sm WITH replication = {
  'class': 'SimpleStrategy',
  'replication_factor': 1
};

USE sm;

CREATE TABLE newdata (timestamp timestamp,
  deviceid int, tagid int,
  decvalue decimal,
  alphavalue text,
  PRIMARY KEY (deviceid,tagid,timestamp));

在主键中,我将 deviceid 设置为分区键,这意味着具有相同设备 ID 的所有数据都将写入一个节点(是指一台机器还是一个分区。每个分区最多可以有 20 亿行),如果我在同一节点内查询数据,检索会很快,我说的对吗?我是 Cassandra 的新手,对分区键和集群键有点困惑。

我的大部分查询如下:

  • 选择已知 deviceid 和 tagid 的最新时间戳
  • 选择已知 deviceid 和 tagid 以及时间戳的 decvalue
  • 选择已知 deviceid 和 tagid 以及时间戳的字母值
  • select * of known deviceid and tagid with time range
  • 选择 * of known deviceid with time range

我将有大约 2000 个 deviceid,每个 deviceid 将有 60 个 tagid/value 对。我不确定它是否会是一大排设备ID、时间戳、标记ID/值、标记ID/值......

【问题讨论】:

    标签: php cassandra cql cqlsh


    【解决方案1】:

    我是 Cassandra 的新手,对分区键和集群键有点困惑。

    听起来您了解分区键,所以我将添加您的分区键帮助 Cassandra 确定集群中存储数据的位置(哪个令牌范围)。每个节点负责几个主要令牌范围(假设是 vnode)。当您的数据写入数据分区时,它会按您的集群键排序。这也是它在磁盘上的存储方式,因此请记住,您的集群键决定了数据在磁盘上的存储顺序。

    每个分区最多可以有 20 亿行

    这并不完全正确。每个分区最多可支持 20 亿个单元。单元格本质上是一个列名/值对。并且您的聚类键本身会加起来一个单元格。因此,通过计算您为每个 CQL 行存储的列值来计算您的单元格,如果您使用聚类列,则再添加一个。

    根据您的宽行结构,您的行数可能会远远少于 20 亿行。此外,这只是存储限制。即使您设法在单个分区中存储 100 万条 CQL 行,查询该分区也会返回大量数据,以至于它会很笨拙并且可能会超时。

    如果我在同一个节点内查询数据,检索会很快,对吗?

    它至少比命中多个节点的多键查询要快。但它是否会“快速”取决于其他因素,例如行的宽度,以及执行删除和就地更新等操作的频率。

    我的大部分查询如下:

    select lastest timestamp of know deviceid and tagid
    Select decvalue of known deviceid and tagid and timestamp
    Select alphavalue of known deviceid and tagid and timestamp
    select * of know deviceid and tagid with time range
    select * of known deviceid with time range
    

    您当前的数据模型可以支持所有这些查询,最后一个除外。为了对timestamp 执行范围查询,您需要将数据复制到一个新表中,并构建一个主键来支持该查询模式。这称为“基于查询的建模”。我会建立一个这样的查询表:

    CREATE TABLE newdata_by_deviceid_and_time (
      timestamp timestamp,
      deviceid int,
      tagid int,
      decvalue decimal,
      alphavalue text,
      PRIMARY KEY (deviceid,timestamp));
    

    该表可以支持对timestamp 的范围查询,同时对deviceid 进行分区。

    但我发现这两种模型中最大的问题是“无限制的行增长”。基本上,随着您为设备收集越来越多的值,您将接近每个分区 20 亿个单元的限制(同样,在此之前事情可能会变得缓慢)。您需要做的是使用一种称为“时间分段”的建模技术。

    例如,我会说我确定按月分桶将使我保持在 20 亿个单元格限制以下并且允许我需要的日期范围灵活性类型。如果是这样,我将添加一个额外的分区键monthbucket,我的(新)表将如下所示:

    CREATE TABLE newdata_by_deviceid_and_time (
      timestamp timestamp,
      deviceid int,
      tagid int,
      decvalue decimal,
      alphavalue text,
      monthbucket text,
      PRIMARY KEY ((deviceid,monthbucket),timestamp));
    

    现在,当我想查询特定设备和日期范围内的数据时,我还会指定monthbucket

    SELECT * FROM newdata_by_deviceid_and_time
    WHERE deviceid='AA23' AND monthbucket='201603'
    AND timestamp >= '2016-03-01 00:00:00-0500'
    AND timestamp < '2016-03-16 00:00:00-0500';
    

    请记住,monthbucket 只是一个示例。对您而言,使用季度甚至年度可能更有意义(假设您一年内每个 deviceid 没有存储太多值)。

    【讨论】:

    • 非常感谢亚伦!这真的很有帮助......我会按照你的建议做我也尝试削减我的数据模型的一些脂肪,因为 cassandra 消耗 CPU、RAM、IO 和存储的方式比 Mongo 高得多。
    • 嗨 Aaron,为了优化这个数据模型,我可以使用 map {'tagid1':value1,'tagid2':value2} 创建表吗,我可以通过这样做来减少硬件需求而不会受到影响表现如何?
    • @PhuongLe 不,将所有数据存储在地图或连接字符串中不会获得任何性能。
    • 在分区键上,我可以将 deviceid 与当单元数达到 10 亿时自动增加的列进行比较?有没有像这样的细胞计数功能或技术?谢谢
    猜你喜欢
    • 2019-07-29
    • 1970-01-01
    • 2011-01-13
    • 2015-07-18
    • 1970-01-01
    • 2018-02-08
    • 2016-02-06
    • 2018-11-08
    • 2018-07-06
    相关资源
    最近更新 更多