我有现场总线数据,这些数据以数据包形式发送,并包含来自数据源的数据(例如浮点数)。
=>我得到了带有源ID和值的时间戳。
现在我想创建一个小程序(实际上是C ++中的日志记录守护程序,通过HTTP提供查询接口以在绘图中显示数据),用户可以在其中选择一些来源和有趣的时间范围,然后获取数据。 这个deamon将在基于Linux的嵌入式系统下运行。
所以我的问题是:该数据的最有效(查询性能和内存消耗)数据存储方案是什么?
附录#1:
虽然我认为算法问题非常有趣,但我会提供一些关于导致这个问题的问题的信息:
做一些数学运算:
附录#2:
这个问题基本上问我如何将2D数据集(时间和ID是维度)传输到内存中(并从那里将其序列化为文件)。而约束是两个维度都将被过滤。
建议的时间排序数组是处理时间维度的明显解决方案。 (为了提高查询性能,可能会使用基于树的索引。二进制搜索本身并不容易,因为每个条目可能具有不同的大小 - 但索引树很好地涵盖了它,并且基本上具有相同的基本思想。)
走这条路线(第一个维度(时间),然后是另一个)会导致ID过滤性能不佳(我担心),因为我必须使用暴力查找。
答案 0 :(得分:3)
您可以将数据存储在SQLite中,让您的网络服务器针对它运行SQL查询。使用现有工具,您可以快速进行原型设计,并了解它的适用范围。
答案 1 :(得分:1)
效率最高(查询性能和 记忆消耗)
通过这个你可能意味着两者之间很平衡的东西。另外,我认为数据插入必须很快。
最简单且可能足够的解决方案是使用普通数组IMO,因为它是可以存储数据的大多数内存有效的非压缩形式。因此,每个数组元素都包含timestamp, id and value
。
使用两个时间戳begin
和end
查询数据时,可以使用binary search
确定数组中时间戳的位置。然后,遍历所有元素并仅获取您感兴趣的具有id-s数据源的元素。数组元素当然必须按时间戳排序。
当然还有其他可能涉及将事务存储在树,哈希表或将这些事件与列表混合在一起的事情,以在性能/内存消耗之间获得更详细的平衡。
此外,当日志量很大时,会出现问题。在这种情况下,您应该将数组拆分为文件并存储文件包含日志的开始/结束时间戳。然后实现变得有点复杂。
希望这有助于您确定解决方案的最佳数据结构/实现。
答案 2 :(得分:1)
这实际上取决于具体情况,但我认为可能的解决方案是将事件存储在页面中并将内容保存在页面目录中:
struct Page
{
int id;
int timestamp0, timestamp1;
int bytes_used;
};
每个页面只有特定ID的事件,所有页面大小相同(例如4K)。 收到活动时,如果适合,请将其添加到特定页面,否则为该活动ID分配新页面。
在进行搜索时,您可以通过查看索引来快速决定数据文件中的哪些页面值得处理,而您不必处理整个文件。
用于添加事件的伪代码是:
进行搜索:
(page.timestamp0 >= tsmax || page.timestamp1 < tsmin)
,则该页面不包含任何有趣的事件,请转到下一个tsmin ... tsmax
中包含的事件。如果每页添加一次ID字段,也可以避免将索引存储在文件中(使事件记录操作更快)。就在启动服务器时,需要对所有数据进行全面扫描......这可能是否是一个有趣的选择。
您还可以轻松决定要保留多少数据......当没有更多免费页面可用时,您可以重复使用(可能是在存储压缩副本进行存档之后)所有仅包含特定日期之前的事件的页面。