4. 历史数据查询语言与API
历史库的价值不在于“存了多少点”,而在于“能不能按需把点取出来”。电力监控系统里,一条10kV线路的有功功率可能每秒采集一次,一天就是86400个原始点;若直接全量拉取,既慢又难用。因此,历史数据查询的核心是四件事:用类SQL语言描述要什么、用时间范围限定取哪一段、用插值把不规则时间戳对齐到统一网格、用聚合函数把密集点压缩成有意义的统计量。理解这四层,才能写出既正确又高效的历史查询。
一、SQL-like查询:把“测点”当作表来查
多数历史库(PI、eDNA、InfluxDB、OpenTSDB及国产实时库)都提供类SQL接口。它和关系库最大的区别是:表名通常对应测点或测点集合,时间列是隐含的主键。典型结构如下:
SELECT value, quality
FROM Line01.ActivePower
WHERE time BETWEEN '2024-06-01 00:00:00' AND '2024-06-01 23:59:59'
AND quality = 'GOOD'
ORDER BY time ASC
其中 Line01.ActivePower 是测点路径(类似表名),time 是时间过滤条件,quality 用于剔除坏点。需要特别注意的是:时间范围过滤是历史查询的第一道性能闸门。没有时间条件的查询在PI等系统中会被拒绝或返回超时,因为历史库按时间分块存储,只有限定区间才能命中对应归档文件。工程上建议:查询跨度不超过24小时时用原始精度;超过7天时先做1分钟或15分钟聚合,再取回结果。
二、插值查询:让不同测点对齐到同一时间轴
实际系统中,线路有功功率、电流、电压的采集时刻往往不完全一致,直接按原始时间戳拼接会出现“同一行里三个值来自三个不同时刻”的问题。插值查询解决的就是这个对齐问题。常见插值方式有三类:
- 前值保持(Previous/Step):取查询时刻之前最近的一个有效值,适合开关状态、档位等离散量。
- 线性插值(Linear):在相邻两点间按时间比例计算,适合功率、温度等连续量。
- 时间加权平均(Time-weighted Average):按每个值持续的时间长度加权,适合计算一段时间的平均功率。
例如要得到每5分钟一个点的24小时有功功率曲线,可写成:
SELECT INTERP(value, '5m', 'LINEAR') AS p_avg
FROM Line01.ActivePower
WHERE time BETWEEN '2024-06-01 00:00:00' AND '2024-06-01 23:59:59'
AND quality = 'GOOD'
这里 '5m' 是插值周期,'LINEAR' 是插值算法。结果会输出288个等间隔点(24×60÷5),每个点都是该5分钟窗口内的线性插值结果。若改用 'TIME_WEIGHTED',则得到的是时间加权平均值,更贴近电能计量口径。
三、聚合函数:把密集点压缩成统计量
当查询跨度大、原始点太多时,聚合函数是必选项。历史库常用聚合包括:AVG、MAX、MIN、SUM、COUNT、STDDEV、RANGE(最大值减最小值)。它们通常与时间分桶配合使用:
SELECT BUCKET(time, '15m') AS ts,
AVG(value) AS p_avg,
MAX(value) AS p_max,
MIN(value) AS p_min
FROM Line01.ActivePower
WHERE time BETWEEN '2024-06-01 00:00:00' AND '2024-06-01 23:59:59'
GROUP BY BUCKET(time, '15m')
这条查询把一天切成96个15分钟桶,每个桶输出平均、最大、最小有功功率。对于负荷分析,MAX用于判断峰值是否越限,AVG用于计算负荷率,RANGE用于评估波动幅度。注意:聚合前必须确认坏点已被过滤,否则一个坏点可能把最大值拉高到不合理水平。
四、常用历史库API:PI SDK、REST、OPC HDA
不同系统提供的访问方式不同,选型时主要看集成环境和实时性要求:
| API类型 | 典型场景 | 特点 |
|---|---|---|
| PI SDK / AF SDK | PI System内部应用、C#/Java客户端 | 功能最全,支持批量读取、插值、聚合,需安装客户端库 |
| REST / Web API | Web前端、跨平台、轻量集成 | 基于HTTP+JSON,易用但大批量查询性能弱于SDK |
| OPC HDA | 多厂商历史库互操作、SCADA集成 | 标准化接口,支持ReadRaw、ReadProcessed、ReadAtTime |
以PI Web API为例,读取24小时插值曲线的请求大致如下:
GET /piwebapi/streams/{webId}/interpolated
?startTime=2024-06-01T00:00:00Z
&endTime=2024-06-01T23:59:59Z
&interval=5m
&filterExpression=quality='GOOD'
OPC HDA则通过 ReadProcessed 方法传入聚合类型和周期,由服务器端完成计算。无论哪种API,核心参数都是:测点标识、起止时间、采样周期、聚合/插值方式、质量过滤。这五个参数决定了返回数据的粒度和可信度。
五、实战:编写查询获取某线路24小时有功功率曲线
假设某10kV线路测点为 Line01.ActivePower,单位kW,采集周期1s,需要获取2024年6月1日全天24小时、每5分钟一个点的有功功率曲线,用于绘制趋势图并计算日负荷率。完整实现分三步:
第一步:确定查询参数。测点标识 Line01.ActivePower;起止时间 2024-06-01 00:00:00 至 2024-06-01 23:59:59;采样周期5分钟;插值方式线性;质量过滤 GOOD。预期返回288个点。
第二步:编写查询。若使用PI Web API,请求如下:
GET /piwebapi/streams/{Line01_ActivePower_WebId}/interpolated
?startTime=2024-06-01T00:00:00Z
&endTime=2024-06-01T23:59:59Z
&interval=5m
&filterExpression=quality='GOOD'
若使用OPC HDA,则调用 ReadProcessed,参数为:ItemID=Line01.ActivePower、AggregateType=INTERPOLATIVE、ResampleInterval=300000(毫秒)、StartTime/EndTime同上。
第三步:结果判读。返回的288个点应满足:时间戳严格等间隔5分钟;值域在合理范围内(例如该线路额定功率5000kW,则曲线应在0~5000kW之间,若出现负值需检查是否反向潮流或接线极性);质量码全部为GOOD。若某点缺失,插值查询会返回前值或线性补点,但应在结果中标记为“插值点”以便区分。日负荷率可用 AVG/MAX 计算,若平均功率为3200kW、最大功率为4800kW,则日负荷率约为66.7%,属于正常波动范围。
掌握这四层查询能力后,历史库就不再是“只能看不能算”的黑盒。无论是画趋势、算负荷率,还是做越限统计,都可以用一条结构清晰的查询完成。关键在于:时间范围先收窄,插值方式选对,聚合粒度匹配分析目标,质量过滤不可省略。