DocumentDB - 存储遥测数据

DocumentDB - Storing telemetry data

快速更新一下我为什么提出这个问题。

我们目前正在 Azure SQL 服务器的现场存储我们设备的遥测数据。这很好用(在 EF、LINQ 和关系数据库方面有大量经验)但我知道这很可能不是最好的解决方案,尤其是对于存储 "big" 数据(数据目前仍然很小,但会在一年)。

我选择了 DocumentDB 作为我们仅存储事件历史记录的可能解决方案。其余的将留在 SQL - 用户、配置文件、设备信息、sim 卡、车辆等,因为我不想完全停止开发,因为我们将 100% 转移到 docdb,而只是做最好的短期 - 成本 + 性能.

看完这个视频,我终于想出了一个关于如何存储遥测数据的可能解决方案 - https://www.youtube.com/watch?v=-o_VGpJP-Q0 他们建议每个时间段一个文档(例如每小时使用 1 个)。这仍然是推荐的方法吗?

    [Index]
    public DateTime TimestampUtc { get; set; }
    public DateTime ReceivedTimestampUtc { get; set; }
    [Index]
    public EventType EventType { get; set; }
    public Guid ConnectionId { get; set; }
    public string RawEventMessage { get; set; }
    [Index]
    public Sender Sender { get; set; }
    [Index]
    public Channel Channel { get; set; }
    public DbGeography Location { get; set; }
    public double? Speed { get; set; }
    public double? Altitude { get; set; }
    public Int16? Heading { get; set; }
    public Byte? HDOP { get; set; }
    public Byte? GPSFixStatus { get; set; }
    public Byte? GPSFixType { get; set; }
    public string Serial { get; set; }
    public string HardwareVersion { get; set; }
    public string FirmwareVersion { get; set; }
    public string Relay1 { get; set; }
    public string Relay2 { get; set; }
    public string Relay3 { get; set; }
    public string Ign { get; set; }
    public string Doors { get; set; }
    public string Input1 { get; set; }
    public string Input2 { get; set; }
    public string Out1 { get; set; }
    public string Out2 { get; set; }
    public int V12 { get; set; }
    public int VBat { get; set; }

这是几种可能的选择之一。哪个最好取决于您的数据是什么样的。例如,如果您的事件在开始 date/time 和持续时间(或结束 date/time)上有所不同,或者如果您跟踪实体的所有状态变化,那么类似 Richard Snodgrass' temporal data model is ideal. Interestingly Microsoft SQL Server 2016 recently added direct support for temporal tables but they've been in the SQL spec as TSQL2 for a while. Note, the TSQL2 spec includes both valid-time and transaction-time 的支持,但我相信最近的 MS SQL 2016 添加仅支持有效时间...但这没关系,因为这是最有价值的。我之所以指出这一点,是因为在不增加事务时间的复杂性的情况下,了解有效时间 table 的工作原理已经足够困难了。

这种方法的优点在于,您不必在收集数据时决定所需的时间粒度,只需 if/when 汇总即可。

但是,正如您所说,SQL 对于如此大的数据集来说并不理想。因此,我在我的 Lumenize library in particular the TimeSeriesCalculator and its other time-series functionality. Read pages 10-19 here 中的 DocumentDB 之上实现了有效时间 Richard Snodgrass 风格的时间模型,作为数据模型的背景知识和 Lumenize 时间序列分析中的常见操作。该平台是我在 Rally 上做的一个实现,称为 Lookback API 建立在 MongoDB 上,但概念是相同的,我现在已经切换到 DocumentDB(但 Rally 还没有)。

关于您提出的模型的另一条评论,您可能希望为每次阅读考虑一个单独的文档。如果每分钟有一个文档或每个设备有一个文档,那么这个例子有点令人困惑。如果它是每小时每台设备一个,那么你可以放心,你永远不会超过 60 分钟,这没关系,但在我能想到的几乎所有其他方式中,看起来你有一个单一的风险文档无限制地增长,这是 DocumentDB 中的一大禁忌(以及所有 NoSQL 数据建模)。另外,正如您所说,即使它不是无限的,它也会涉及很多就地更新。由于您的系统可能写入繁重,我建议您每次阅读一个文档可能会更好。如果您以后必须存储非规范化聚合以提高速度,那么您仍然可以选择这样做。你甚至可能不需要它。让生产系统的性能为该决定提供信息。

我建议您阅读星型模式的时间维度。它看起来很像您的计划,但它也非常适合我描述的非规范化聚合存储。我还没有看到任何有关 NoSQL 星型模式概念的文章,但 here 是来自传统 SQL 世界的一篇文章,可以帮助您理解这些概念。

正如我所说,有很多选择,在不了解您的情况的情况下,我不知道哪个是最好的。

好的,所以我想我要为每个事件准备 1 个文档(现在每 5 分钟 1 个,但可以更改为每台设备每秒 1 个)。附加到文档的原因肯定是昂贵的,因为您需要对该文档执行 "replace"? (docdb 现在支持 append/partial 更新吗?)当然,这涉及到读取,然后是不断增长的替换,这比每个事件只添加一个新文档更昂贵和更及时。唯一担心的是当我们有 millions/billions 份文件时...这样可以吗?