我使用Influx来存储我们的时间序列数据。它工作时很酷,然后大约一个月后,它停止工作,我无法弄清楚原因。 (与此问题类似https://github.com/influxdb/influxdb/issues/1386)
也许Influx有一天会很棒,但是现在我需要使用更稳定的东西。我正在考虑Postgres。我们的数据来自许多传感器,每个传感器都有一个传感器ID。所以我正在考虑构建我们的数据:
(pk),sensorId(string),time(timestamp),value(float)
Influx是为时间序列数据构建的,因此它可能有一些内置的优化。我是否需要自己进行优化才能使Postgres高效?更具体地说,我有这些问题:
Influx有“系列”这个概念,创建新系列很便宜。所以每个传感器都有一个单独的系列。我应该为每个传感器创建一个单独的Postgres表吗?
我应该如何设置索引以快速查询?典型的查询是:在过去3天内选择sensor123的所有数据。
我应该在时间列中使用时间戳或整数吗?
如何设置保留政策?例如。删除超过一周的数据。
Postgres会水平缩放吗?我可以为数据复制和负载平衡设置ec2集群吗?
我可以在Postgres中进行缩减采样吗?我在一些文章中读过我可以使用date_trunc。但似乎我无法将日期_特征发送到特定的时间间隔,例如25秒。
我错过了其他任何警告?
提前致谢!
更新 将时间列存储为大整数比将其存储为时间戳要快。我做错了吗?
将其存储为时间戳:
postgres=# explain analyze select * from test where sensorid='sensor_0';
Bitmap Heap Scan on test (cost=3180.54..42349.98 rows=75352 width=25) (actual time=10.864..19.604 rows=51840 loops=1)
Recheck Cond: ((sensorid)::text = 'sensor_0'::text)
Heap Blocks: exact=382
-> Bitmap Index Scan on sensorindex (cost=0.00..3161.70 rows=75352 width=0) (actual time=10.794..10.794 rows=51840 loops=1)
Index Cond: ((sensorid)::text = 'sensor_0'::text)
Planning time: 0.118 ms
Execution time: 22.984 ms
postgres=# explain analyze select * from test where sensorid='sensor_0' and addedtime > to_timestamp(1430939804);
Bitmap Heap Scan on test (cost=2258.04..43170.41 rows=50486 width=25) (actual time=22.375..27.412 rows=34833 loops=1)
Recheck Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > '2015-05-06 15:16:44-04'::timestamp with time zone))
Heap Blocks: exact=257
-> Bitmap Index Scan on sensorindex (cost=0.00..2245.42 rows=50486 width=0) (actual time=22.313..22.313 rows=34833 loops=1)
Index Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > '2015-05-06 15:16:44-04'::timestamp with time zone))
Planning time: 0.362 ms
Execution time: 29.290 ms
将其存储为大整数:
postgres=# explain analyze select * from test where sensorid='sensor_0';
Bitmap Heap Scan on test (cost=3620.92..42810.47 rows=85724 width=25) (actual time=12.450..19.615 rows=51840 loops=1)
Recheck Cond: ((sensorid)::text = 'sensor_0'::text)
Heap Blocks: exact=382
-> Bitmap Index Scan on sensorindex (cost=0.00..3599.49 rows=85724 width=0) (actual time=12.359..12.359 rows=51840 loops=1)
Index Cond: ((sensorid)::text = 'sensor_0'::text)
Planning time: 0.130 ms
Execution time: 22.331 ms
postgres=# explain analyze select * from test where sensorid='sensor_0' and addedtime > 1430939804472;
Bitmap Heap Scan on test (cost=2346.57..43260.12 rows=52489 width=25) (actual time=10.113..14.780 rows=31839 loops=1)
Recheck Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > 1430939804472::bigint))
Heap Blocks: exact=235
-> Bitmap Index Scan on sensorindex (cost=0.00..2333.45 rows=52489 width=0) (actual time=10.059..10.059 rows=31839 loops=1)
Index Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > 1430939804472::bigint))
Planning time: 0.154 ms
Execution time: 16.589 ms
答案 0 :(得分:1)
您不应该为每个传感器创建一个表。相反,您可以在表中添加一个字段来标识它所在的系列。您还可以使用另一个表来描述该系列的其他属性。如果数据点可能属于多个系列,那么您需要完全不同的结构。
对于您在q2中描述的查询,您的recorded_at列上的索引应该有效(时间是一个sql保留关键字,所以最好避免使用它作为名称)
您应该使用TIMESTAMP WITH TIME ZONE作为您的时间数据类型。
保留取决于你。
Postgres有多种分片/复制选项。这是一个很大的话题。
我不确定我理解你对#6的目标,但我确定你能解决问题。