时间序列数据的 Cassandra 分区键
Cassandra partition key for time series data
我正在测试 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));
在Primary key中,我设置了deviceid作为partition key,这意味着所有具有相同设备id的数据将写入一个节点(它是指一台机器还是一个分区。每个分区最多可以有20亿行)也如果我在同一节点内查询数据,检索速度会很快,对吗?我是 Cassandra 的新手,对分区键和集群键有点困惑。
我的大部分查询如下:
- select 知道 deviceid 和 tagid 的最新时间戳
- Select 已知 deviceid 和 tagid 以及时间戳的 decvalue
- Select 已知 deviceid 和 tagid 以及时间戳的 alphavalue
- select * of know deviceid and tagid with time range
- select * 具有时间范围的已知设备 ID
我将有大约 2000 个 deviceid,每个 deviceid 将有 60 tagid/value 对。不知道会不会是一大排deviceid, timestamp, tagid/value, tagid/value...
I’m new to Cassandra and a bit confused about the partition key and clustering key.
听起来您了解分区键,所以我只想补充一点,您的分区键可以帮助 Cassandra 确定在集群中的哪个位置(哪个令牌范围)存储您的数据。每个节点负责几个主要令牌范围(假设 vnodes)。当您的数据写入数据分区时,它会按您的集群键排序。这也是它在磁盘上的存储方式,因此请记住,您的集群键决定了数据在磁盘上的存储顺序。
Each partition can have max 2 billion rows
这不完全正确。每个分区最多可支持 20 亿个 单元 。一个单元格本质上是一个列 name/value 对。你的集群键自己加起来就是一个单元格。因此,通过计算为每个 CQL 行存储的列值来计算单元格,如果使用聚类列,则再添加一个。
根据您的宽行结构,您的行数限制可能远少于 20 亿行。此外,这只是存储限制。即使您设法在单个分区中存储 100 万个 CQL 行,查询该分区也会 return 如此多的数据,以至于它会很笨拙并且可能会超时。
if I query data within the same node, the retrieval will be fast, am I correct?
它至少比命中多个节点的多键查询要快。但它是否 "fast" 取决于其他因素,例如行的宽度,以及执行删除和就地更新等操作的频率。
Most of my query will be as below:
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
上执行范围查询,您需要将数据复制到新的 table 中,并构建一个 PRIMARY KEY 来支持该查询模式。这称为 "query-based modeling." 我会像这样构建一个查询 table:
CREATE TABLE newdata_by_deviceid_and_time (
timestamp timestamp,
deviceid int,
tagid int,
decvalue decimal,
alphavalue text,
PRIMARY KEY (deviceid,timestamp));
table 可以支持在 timestamp
上进行范围查询,而在 deviceid
上进行分区。
但我看到的这两种模型中的最大问题是 "unbounded row growth." 基本上,随着您为设备收集越来越多的值,您将接近每个分区 20 亿个单元的限制(并且再说一遍,在那之前事情可能会变得很慢)。您需要做的是使用一种称为 "time bucketing."
的建模技术
例如,我会说我确定按月分桶将使我很好地保持在 20 亿个单元格限制以下 并且 允许日期范围灵活性的类型我需要。如果是这样,我将添加一个额外的分区键 monthbucket
并且我的(新)table 将如下所示:
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 作为时间序列数据库。
我创建数据模型如下:
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));
在Primary key中,我设置了deviceid作为partition key,这意味着所有具有相同设备id的数据将写入一个节点(它是指一台机器还是一个分区。每个分区最多可以有20亿行)也如果我在同一节点内查询数据,检索速度会很快,对吗?我是 Cassandra 的新手,对分区键和集群键有点困惑。
我的大部分查询如下:
- select 知道 deviceid 和 tagid 的最新时间戳
- Select 已知 deviceid 和 tagid 以及时间戳的 decvalue
- Select 已知 deviceid 和 tagid 以及时间戳的 alphavalue
- select * of know deviceid and tagid with time range
- select * 具有时间范围的已知设备 ID
我将有大约 2000 个 deviceid,每个 deviceid 将有 60 tagid/value 对。不知道会不会是一大排deviceid, timestamp, tagid/value, tagid/value...
I’m new to Cassandra and a bit confused about the partition key and clustering key.
听起来您了解分区键,所以我只想补充一点,您的分区键可以帮助 Cassandra 确定在集群中的哪个位置(哪个令牌范围)存储您的数据。每个节点负责几个主要令牌范围(假设 vnodes)。当您的数据写入数据分区时,它会按您的集群键排序。这也是它在磁盘上的存储方式,因此请记住,您的集群键决定了数据在磁盘上的存储顺序。
Each partition can have max 2 billion rows
这不完全正确。每个分区最多可支持 20 亿个 单元 。一个单元格本质上是一个列 name/value 对。你的集群键自己加起来就是一个单元格。因此,通过计算为每个 CQL 行存储的列值来计算单元格,如果使用聚类列,则再添加一个。
根据您的宽行结构,您的行数限制可能远少于 20 亿行。此外,这只是存储限制。即使您设法在单个分区中存储 100 万个 CQL 行,查询该分区也会 return 如此多的数据,以至于它会很笨拙并且可能会超时。
if I query data within the same node, the retrieval will be fast, am I correct?
它至少比命中多个节点的多键查询要快。但它是否 "fast" 取决于其他因素,例如行的宽度,以及执行删除和就地更新等操作的频率。
Most of my query will be as below:
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
上执行范围查询,您需要将数据复制到新的 table 中,并构建一个 PRIMARY KEY 来支持该查询模式。这称为 "query-based modeling." 我会像这样构建一个查询 table:
CREATE TABLE newdata_by_deviceid_and_time (
timestamp timestamp,
deviceid int,
tagid int,
decvalue decimal,
alphavalue text,
PRIMARY KEY (deviceid,timestamp));
table 可以支持在 timestamp
上进行范围查询,而在 deviceid
上进行分区。
但我看到的这两种模型中的最大问题是 "unbounded row growth." 基本上,随着您为设备收集越来越多的值,您将接近每个分区 20 亿个单元的限制(并且再说一遍,在那之前事情可能会变得很慢)。您需要做的是使用一种称为 "time bucketing."
的建模技术例如,我会说我确定按月分桶将使我很好地保持在 20 亿个单元格限制以下 并且 允许日期范围灵活性的类型我需要。如果是这样,我将添加一个额外的分区键 monthbucket
并且我的(新)table 将如下所示:
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
没有存储太多值)。