微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

postgresql – 如何存储时间序列数据

我有一个我相信的时间序列数据集(请纠正我,如果我错了),它有一堆相关的值.

一个例子是在旅行期间对汽车进行建模并跟踪其各种属性.例如:

时间戳|速度|旅行距离|温度|等等

存储此数据的最佳方法是什么,以便Web应用程序可以有效地查询字段以查找最长,分钟和绘制每个数据集的时间?

我开始了一种简单的方法来解析数据转储并缓存结果,以便永远不必存储它们.然而,在使用它之后,由于内存限制,此解决方案似乎不会长期扩展,如果要清除缓存,则需要重新解析和重新缓存所有数据.

另外,假设每秒钟跟踪数据的可能性很小,10小时数据集,是否通常建议每隔N秒采样一次截断数据集?

实际上没有一种“最好的方法”来存储时间序列数据,它实际上取决于许多因素.但是,我将主要关注两个因素,它们是:

(1)这个项目有多重要,它值得您优化架构?

(2)您的查询访问模式真的会是什么样的?

考虑到这些问题,让我们讨论一些模式选项.

平表

使用平面表的选项与问题(1)有很多关系,如果这不是一个严肃的或大规模的项目,你会发现更容易不去思考模式,以及只需使用一张平台,如:

CREATE flat_table(
  trip_id integer,tstamp timestamptz,speed float,distance float,temperature float,...);

我推荐这门课程的情况并不多,只有这是一个很小的项目,不能保证你的大部分时间.

维度和事实

因此,如果您已经清除了问题(1)的障碍,并且您想要更高性能的架构,那么这是首先要考虑的选项之一.它包括一些基本的规范化,但从测量的“事实”数量提取“维度”数量.

基本上,你需要一个表来记录有关旅行的信息,

CREATE trips(
  trip_id integer,other_info text);

一个记录时间戳的表,

CREATE tstamps(
  tstamp_id integer,tstamp timestamptz);

最后所有测量的事实,对维度表的外键引用(即meas_facts(trip_id)引用trip(trip_id)& meas_facts(tstamp_id)引用tstamps(tstamp_id))

CREATE meas_facts(
  trip_id integer,tstamp_id integer,...);

这看起来似乎没有那么有用,但如果你有数千个并发旅行,那么他们可能每秒都进行一次测量,第二次.在这种情况下,您必须每次为每次旅行重新记录时间戳,而不是仅使用tstamps表中的单个条目.

使用案例:如果您要记录数据的并发行程很多,并且您不介意同时访问所有测量类型,则此情况会很好.

由于Postgres按行读取,任何时候你需要,例如,在给定时间范围内的速度测量,你必须从meas_facts表读取整行,这肯定会减慢查询速度,不过如果数据集你正在工作与不是太大,那么你甚至不会注意到差异.

拆分您的测量事实

为了进一步扩展最后一部分,您可以将测量分解为单独的表,我将显示表格的速度和距离:

CREATE speed_facts(
  trip_id integer,speed float);

CREATE distance_facts(
  trip_id integer,distance float);

当然,您可以看到如何将其扩展到其他测量.

使用案例:因此,这不会为您提供极大的查询速度,当您查询一种测量类型时,可能只是速度的线性增加.这是因为当您想要查找有关速度的信息时,您只需要读取speed_facts表中的行,而不是在meas_facts表的行中存在的所有额外的,不需要的信息.

因此,您只需阅读有关一种测量类型的大量数据,您就可以获得一些好处.建议您以一秒为间隔的10小时数据的情况下,您只能阅读36,000行,因此您从未真正从中获得显着的好处.但是,如果您要查看大约10个小时的5,000次旅行的速度测量数据,那么现在您正在寻找1.8亿行.只要您一次只需要访问一个或两个测量类型,这种查询的速度线性增加就可以产生一些好处.

数组/ HStore /&土司

您可能不需要担心这部分,但我知道它确实重要的情况.如果您需要访问大量的时间序列数据,并且您知道需要在一个巨大的块中访问所有这些数据,则可以使用将使用TOAST Tables的结构,该结构实质上将您的数据存储在较大的压缩段中.只要您的目标是访问所有数据,这样可以更快地访问数据.

一个示例实现可以是

CREATE uber_table(
  trip_id integer,tstart timestamptz,speed float[],distance float[],temperature float[],...);

在此表中,tstart将存储数组中第一个条目的时间戳,并且每个后续条目将是下一秒的读数值.这要求您在一个应用程序软件中管理每个数组值的相关时间戳.

另一种可能性是

CREATE uber_table(
  trip_id integer,speed hstore,distance hstore,temperature hstore,...);

将测量值添加为(键,值)对(时间戳,测量).

使用案例:这个实现可能最好留给对Postgresql更熟悉的人,并且只有当您确定您的访问模式需要批量访问模式时.

结论是什么?

哇,这比我想象的要长得多,抱歉.

原文地址:https://www.jb51.cc/postgresql/192235.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐