我在用postgresql v10.12
表1:总行数阈值 ~800
(每个传感器的最小和最大阈值水平存储在此表中)
说明:
SensorName Varchar(10),
MinLimit numeric,
MaxLimit numeric
数据:
SensorName | MinLimit | MaxLimit
Sensor1 | 80 | 115
Sensor2 | 60 | 70
Sensor3 | 100 | 120
...
Sensor800 | 60 | 70
表2:包含总列的iotdata ~800+
(阈值表中的每个传感器都是iotdata表中的列)
说明:
IoTDateTime timestamp without time zone,
sensor1 numeric(3)
sensor2 numeric(8,5)
sensor3 numeric(5,2)
....
Sensor800 numeric(5,2)
此表中每5分钟将生成一条记录。此表按日期范围进行分区(4个月的数据将在一个分区中)。同样,到目前为止,这个表有6个分区。
- e、 克:
IoTDateTime | Sensor1
2020-01-01 11:05:00 | 85
2020-01-01 11:10:00 | 80
2020-01-01 11:15:00 | 77
...
2020-01-31 23:50:00 | 70
2020-01-31 23:55:00 | 70
从表1 Threshold
这个 Sensor1
的 MinLimit
是 80
以及 MaxLimit
是 115
. 下面有什么吗 MinLimit
( 80
)或大于 MaxLimit
( 115
)被视为警报或传感器出现故障。
我需要找到每个月每天800多个传感器的警报计数。
我写了下面的函数来执行这个逻辑。
需要您的帮助,以更好的方式重写此函数,以减少代码行和乐观逻辑。提前感谢:)
CREATE OR REPLACE FUNCTION public.udf_SensorFailedForeachDay
( pimono integer,
pstartdate timestamp without time zone,
penddate timestamp without time zone)
RETURNS TABLE(date_of_month double precision, Sensor1 double precision, Sensor2 double precision,
...
, Sensor800 double precision)
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
declare Sensor1min numeric(3);declare Sensor1max numeric(3);
declare Sensor2min numeric(8,5);declare Sensor2max numeric(8,5);
....
declare Sensor800min numeric(5,2);declare Sensor800max numeric(5,2);
BEGIN
select minlimit,maxlimit Into Sensor1min,Sensor1max from threshold where channelname='Sensor1';
select minlimit,maxlimit Into Sensor2min,Sensor2max from threshold where channelname='Sensor2';
...
select minlimit,maxlimit Into Sensor800min,Sensor800max from threshold where channelname='Sensor800';
Return query
select extract(day from a.IoTDateTime) as date_of_month,
(cast(sum(case when a.Sensor1 between Sensor1min and Sensor1max then 1 end) as float)/cast(count(a.IoTDateTime) as float) )*100 as Sensor1,
(cast(sum(case when a.Sensor2 between Sensor2min and Sensor2max then 1 end) as float)/cast(count(a.IoTDateTime) as float))*100 as Sensor2,
...
(cast(sum(case when a.Sensor800 between Sensor800min and Sensor800max then 1 end) as float)/cast(count(a.IoTDateTime) as float))*100 as Sensor800
from IoTData a where a.IoTDateTime between Pstartdate and Penddate
group by extract(day from a.IoTDateTime) order by extract(day from a.IoTDateTime);
END;
$BODY$;
1条答案
按热度按时间elcex8rz1#
如果您有固定数量的传感器并且几乎从不更新行,则将数据存储在
IoTData
对于每个时间戳只有一行的情况,就像您所做的那样,可以获得最小的存储大小和良好的性能。但是,您正接近允许的绝对最大列数,这表明您可能朝着错误的方向移动。请参见:
select或create语句中的数据库列
如果以后需要添加/删除传感器,则必须调整表结构以及依赖于它的所有内容,包括我将提供的函数。痛苦的过程。因此,通常情况下,使用一个更通用的模型,每个度量值有一行(800行而不是只有一行)会更合理。这使存储空间膨胀,但用途更广。
也就是说,它可以这样工作:
db<>在这里摆弄