1

我们从大约 20-25 个工业电机传感器中提取数据,数据存储在 cassandra 数据库中。Cassandra 目前在单个节点中运行。

下面是表结构

CREATE TABLE cisonpremdemo.machine_data (
    id uuid PRIMARY KEY,
    data_temperature bigint,
    data_current bigint,
    data_timestamp timestamp,
    deviceid text,
    
) WITH bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND default_time_to_live = 7884000
    AND gc_grace_seconds = 100;
	
CREATE INDEX deviceid_idx ON db.machine_data (deviceid);
CREATE INDEX data_timestamp_idx ON db.machine_data (data_timestamp);

这张表中的数据被收集了几个月,每 5 秒一次,持续了近 24 小时,因此数据量非常大。

我正在尝试使用 java 和 dotnet 执行基于日期范围的查询,在这两种情况下我都遇到超时错误(Cassandra 在读取查询期间以一致性 LocalOne 失败(0 个副本响应超过 1 个需要))

如果我给出 100 的限制,查询就可以正常工作,否则它会失败。我尝试过的一些事情......

1) 增加查询超时。2) 将 gc_grace_seconds 减少到 100(暂时)以消除任何墓碑。

使用的查询

SELECT data_temperature AS "DATA_TEMP",data_current AS "DATA_CURRENT" FROM machine_data 
WHERE DATA_TIMESTAMP>=1517402474699 
AND DATA_TIMESTAMP<=1517402774699 
AND DEVICEID='BP_100' ALLOW FILTERING;

不确定我的表结构(主键)是否是错误的选择。它应该是 deviceid 和时间戳吗?

4

1 回答 1

2

二级索引几乎肯定会失败。它们应该具有“不低,不高”的基数(这取决于环中的节点数)。很难做到正确,除非有强烈的需求并且数据适合(非规范化表不可能实现跨表一致性),否则您应该避免使用它。

你永远不应该使用的另一件事是allow filtering,那几乎只是用于调试/开发和大型 Spark 工作,有点像读取整个数据集的东西。它非常昂贵,并且几乎总是会导致长期超时。

相反,您应该创建新表并按时间分解它们,这样分区就不会变得太大。IE

CREATE TABLE cisonpremdemo.machine_data_by_time (
    id uuid PRIMARY KEY,
    data_temperature bigint,
    data_current bigint,
    data_timestamp timestamp,
    yymm text,
    deviceid text,
    PRIMARY KEY ((deviceid, yymm), data_timestamp)
) WITH CLUSTERING ORDER BY (data_timestamp DESC);

插入数据时,写入两者。您基本上应该为您拥有的每种请求创建一个表,以便数据采用您需要的格式。不要围绕数据的外观对表格进行建模。如果您不需要通过 uuid 直接查找消息,请不要machine_data像上面那样制作表格,因为这不是您查询它的方式。

于 2018-01-31T16:27:53.127 回答