2

我正在为如何存储一些遥测流而苦苦挣扎。我玩过很多东西,我发现自己感觉像是在作家的街区。

问题描述

通过 UDP 连接,我接收来自不同来源的遥测数据。每个源都分解为一组设备。对于每个设备,我要存储最多 5 种不同的值类型。他们进来的速度不超过每分钟一次,而且可能很少。使用混合边缘/电平触发方案传输值(当值足够不同或经过足够时间时,发送值的数据)。所以它是一个 2 或 3 级层次结构,带有时间序列字典。

我最想对数据做的事情是a)访问最新值和b)枚举时间跨度(开始/结束/值)。我并不真正关心数据之间的很多“相关性”。这不是我想要计算平均值或在它们之间关联的情况。通常,我会查看给定类型的最新值,跨越所有或某些层次结构派生的子集。或者我专注于一个单一的价值流并列举跨度。

我根本不是数据库专家。其实我知道的很少。我的三个同事也不是。我做python(并且希望我做的任何事情都是python3)。所以我希望我们所做的一切都尽可能平易近人。我目前正在尝试使用 Mint Linux 进行开发。我不太关心酸和所有这些。

到目前为止我做了什么

  1. 我们的第一个版本使用了 Gemstone Smalltalk 数据库。构建一个专门的 Timeseries 对象就像一个魅力。我已经做了很多 Smalltalk,但我的同事们还没有,Gemstone 系统不仅仅是“跳进去,马上就开心”。而且我们希望摆脱 Smalltalk(尽管我希望市场能够做到这一点)。所以就这样了。

  2. 与 RRD(循环数据库)一起玩。一种新颖的方法,但我们不需要那么糟糕的压缩,并且被边缘触发,它不适用于我们的数据捕获模型。

  3. 一位朋友说服我使用 sqlite3。我可以再试一次。我的第一次尝试并没有那么好。我可能一直试图太聪明。我试图以“标准化”的方式做事。我发现我一开始就可以正常工作。但是获取设备子集的给定字段的“最新”值,变得有点毛茸茸(对我来说)SQL。这样做的速度有点令人失望。所以事实证明我也需要学习索引。我发现我正在进入一个我不想进入的洞。然后回到我们使用 Smalltalk DB 的地方,有很多专业知识,我是唯一可以使用它的人。

  4. 我以为我会走“自己动手”的路线。我的数据不是很大。磁盘便宜。而且我非常了解如何读/写文件。文件系统不是分层数据库吗?我敢肯定,“知情人士”对这种原始方法嗤之以鼻,但这种方法是最平易近人的。使用一点 python 代码,我使用目录进行结构化,然后为每个值使用 2 个文件方案(一个用于最新值,一个用于其余值的附加日志)。这工作正常。但我宁愿不对我还没有完全解决的皱纹负责。数据如何序列化到/从(现在只使用简单的字符串)涉及到同样多的代码。这种方法的一个好处是,虽然我可以编写 python 脚本来分析数据,有些事情可以用经典的命令行工具来完成。例如(显示所有最新 rssi 值的简单查询)。

    ls Telemetry/*/*/rssi | xargs cat

  5. 我今天早上花了很多时间寻找替代品。增加了 NOSQL 站点。阅读 PyTables。扫描 ZODB 教程。PyTables 看起来非常适合我所追求的。命名表的层次结构建模时间序列。但我认为 PyTables 还不能与 python3 一起使用(至少,还没有适用于 python3 的 debian/ubuntu 包)。ZODB 也是如此。而且恐怕我对许多不同的 NOSQL 数据库所做的事情了解得不够多,甚至无法尝试其中一个。

征求意见

我发现自己比开始时更加困惑和困惑。我可能太天真了,以至于我会发现一些可能更“一劳永逸”的东西,并且在这一点上已经过去了。您有任何建议和方向,将不胜感激。如果有人可以给我一个食谱,我可以在没有大量开销/教育/入口的情况下满足我的需求,我肯定会将其标记为答案。

4

4 回答 4

2

好的,我将对此进行尝试。

我们对很多非结构化数据使用 Elastic Search:http ://www.elasticsearch.org/ 。我不是这方面的专家,但在我的日常工作中,我非常依赖指数。基本上,您将 JSON 对象发布到索引,该索引位于某个服务器上。您可以通过 URL 或通过将 JSON 对象发布到适当的位置来查询索引。我使用pyelasticsearch连接到索引——该包有据可查,并且您使用的主类是线程安全的。

查询语言本身非常健壮,但是您可以在发布记录之前轻松地向索引中的记录添加一个“最新时间”的字段。

无论如何,我觉得这不值得打勾(即使你走那条路),但评论太长了。

于 2013-07-26T22:31:07.570 回答
1

您描述的内容适合数据库模型(例如 sqlite3)。

保留一张桌子。

id, device_id, valuetype1, valuetype2, valuetype3, ... ,valuetypen, timestamp

我假设所有设备都属于同一类型(IE,具有您关心的相同值集)。如果没有,请考虑在 value=null 不适用于特定设备类型时简单地设置它。

每次获得更新时,复制最后一行并更新最新值:

INSERT INTO DeviceValueTable (device_id, valuetype1, valuetype2,..., timestamp) 
    SELECT device_id, valuetype1, @new_value, ...., NOW()
        FROM DeviceValueTable
        WHERE device_id = @device_id
        ORDER BY timestamp DESC
        LIMIT 1;

要获取特定设备的最新值:

SELECT *
    FROM DeviceValueTable
    WHERE device_id = @device_id         
    ORDER BY timestamp DESC
    LIMIT 1;

要获取所有设备的最新值:

select
    DeviceValueTable.*
from
    DeviceValueTable a
    inner join 
        (select id, max(timestamp) as newest 
         from DeviceValueTable group by device_id) as b on
        a.id = b.id

您可能会担心重复值的成本(存储大小)。依靠数据库来处理压缩。另外,请记住简单性优于优化。让它工作,然后如果它太慢,找到并修复缓慢。

请注意,这些查询未在 sqlite3 上测试,可能包含拼写错误。

于 2013-07-28T15:53:30.893 回答
0

在我看来,你想要一个磁盘上的、隐式排序的数据结构,比如 btree 或类似的。

也许看看:

http://liw.fi/larch/
http://www.egenix.com/products/python/mxBase/mxBeeBase/
于 2013-07-26T22:42:02.723 回答
0

您的问题不是技术问题,而是问题规范不佳。

如果您对传感器数据做任何事情,那么旧的实验室格言适用“如果你不写下来,它就不会发生”。在实验室中,这意味着笔记本和笔,在计算机上,这意味着 ACID。

您似乎还过早地优化了解决方案,这是众所周知的万恶之源。您没有说数据的大小,但您确实说它们“每分钟不超过一次,并且可能很稀疏”。假设它们的大小为 1.0KB,即 1.5MB/天或 5.3GB/年。我的 StupidPhone 的存储空间比你一年所需的多,我的笔记本电脑的喷嚏也更大。

最大的问题是您声称对数据库“知之甚少”,这就是问题的症结所在。您的数据是标准的 1950 年代旧数据处理无聊。当 SQLite 只要你知道如何询问它就会做你需要的一切时,你就会跳入流行语存储技术。鉴于您已经关闭了 Smalltalk DB,如果需要一天以上的学习时间来学习您需要的所有传统 RDBM 原则,然后再学习一些,我会感到非常惊讶。

之后,您将能够编写一个可以回答的问题,而不是笼统地回答。

于 2013-07-26T23:09:19.497 回答