2

我正在尝试使用 kdb+ 来捕获并聚合从物联网传感器整理的许多感官流。

每个传感器都有一个唯一标识符、一个时间分量 (.zz) 和一个标量值:

percepts:([]time:`datetime$(); id:`symbol$(); scalar:`float$())

然而,由于数据本质上是时间的,在不同的列中维护单独的感知/感觉流似乎是合乎逻辑的,即:

time  id_1    id_2 ...
15    0.15     ...
16    ...      1.5

然而,附加到表指示性仅支持插入方式的行操作,即感知插入(.zz;`id_1;0.15)

看起来好像我想在此设置中支持大量非静态传感器,附加上述格式的行似乎是一种反模式,然后再进行转换以将行转换为基于列的列他们的身份证。是否有可能/有必要根据新的特征流创建一个具有动态(增长)列数的表?

如何最有效地实现允许插入列式时间序列数据的逻辑,从而避免对基于行的数据进行转换?

4

1 回答 1

1

您可以将数据添加到特定列。为此进行以下更改:

  • time永久或在更新操作期间将列作为键。
  • 用于upsert添加数据并以表格格式传递数据。

我在下面提到的更新功能特定于您的示例,但您可以使其更通用。它将传感器名称和传感器数据作为输入。它执行 3 个步骤:

  • 它首先检查表是否为空,在这种情况下,将表模式设置为输入数据集模式(根据您的示例应该是时间和传感器名称列),并将时间作为主键。
  • 如果表有数据但新传感器缺少该列,则首先添加一个具有空浮点值的列,然后插入数据。
  • 如果一列已经存在,那么只需更新数据。

    q)t:() / table to store all sensors data
    q)upd:{[s;tbl] `t set $[0=count t;`time xkey 0#tbl;not s in cols t;![t;();0b;enlist[s]!enlist count[t]#0Nf];t] upsert tbl}
    
    q)upd[`id1;([]time:1#.z.z;id1:1#14.4)]
    q)upd[`id2;([]time:1#.z.z;id2:1#2.3)]
    
time                    id1  id2
--------------------------------
2019.08.26T13:35:43.203 14.4    
2019.08.26T13:35:46.861      2.3

关于您的设计的一些要点:

如果所有传感器都没有为每个时间条目发送数据,那么该表将有很多空值(类似于稀疏矩阵),这将浪费内存并且也会对查询产生一些影响。在这种情况下,您可以根据您的用例考虑其他设计。例如,不是存储每个时间条目,而是将数据存储在时间桶中。另一种选择是将相关传感器分组到不同的表中,而不是全部存储在一个表中。

您需要考虑的另一点是,如果您继续向其中添加传感器,您将拥有一个胖表,并且它有其自身的问题。此外,它将成为一个单一的瓶颈点,这可能是未来的一个问题,并且很难扩展它。

对于小型传感器组,当前的设计很好,但如果您计划将来添加许多传感器,那么请考虑其他设计选项。

于 2019-08-26T13:37:36.990 回答