目录
-
- 摘要
- 一、生产指标概述
-
- [1.1 KPI指标体系](#1.1 KPI指标体系)
- [1.2 核心KPI指标](#1.2 核心KPI指标)
- [1.3 指标监控目标](#1.3 指标监控目标)
- 二、KPI定义与计算
-
- [2.1 KPI定义表](#2.1 KPI定义表)
- [2.2 产量计算](#2.2 产量计算)
- [2.3 良品率计算](#2.3 良品率计算)
- [2.4 OEE计算](#2.4 OEE计算)
- 三、实时统计
-
- [3.1 时间窗口统计](#3.1 时间窗口统计)
- [3.2 滑动窗口统计](#3.2 滑动窗口统计)
- [3.3 实时聚合引擎](#3.3 实时聚合引擎)
- 四、趋势分析
-
- [4.1 趋势数据](#4.1 趋势数据)
- [4.2 同比环比](#4.2 同比环比)
- [4.3 预测分析](#4.3 预测分析)
- 五、指标告警
-
- [5.1 告警规则](#5.1 告警规则)
- [5.2 告警推送](#5.2 告警推送)
- 六、可视化展示
-
- [6.1 KPI看板数据](#6.1 KPI看板数据)
- [6.2 KPI排名](#6.2 KPI排名)
- 七、实战案例
-
- [7.1 完整KPI监控系统](#7.1 完整KPI监控系统)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB生产指标监控技术。从KPI定义到指标计算,从实时统计到趋势分析,从指标告警到可视化展示,全面介绍生产指标监控的核心方法。通过丰富的代码示例,帮助读者掌握KPI实时计算的核心技能。
一、生产指标概述
1.1 KPI指标体系
#mermaid-svg-iK9yB9hrM0x8HJUd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iK9yB9hrM0x8HJUd .error-icon{fill:#552222;}#mermaid-svg-iK9yB9hrM0x8HJUd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iK9yB9hrM0x8HJUd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iK9yB9hrM0x8HJUd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iK9yB9hrM0x8HJUd .marker.cross{stroke:#333333;}#mermaid-svg-iK9yB9hrM0x8HJUd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iK9yB9hrM0x8HJUd p{margin:0;}#mermaid-svg-iK9yB9hrM0x8HJUd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iK9yB9hrM0x8HJUd .cluster-label text{fill:#333;}#mermaid-svg-iK9yB9hrM0x8HJUd .cluster-label span{color:#333;}#mermaid-svg-iK9yB9hrM0x8HJUd .cluster-label span p{background-color:transparent;}#mermaid-svg-iK9yB9hrM0x8HJUd .label text,#mermaid-svg-iK9yB9hrM0x8HJUd span{fill:#333;color:#333;}#mermaid-svg-iK9yB9hrM0x8HJUd .node rect,#mermaid-svg-iK9yB9hrM0x8HJUd .node circle,#mermaid-svg-iK9yB9hrM0x8HJUd .node ellipse,#mermaid-svg-iK9yB9hrM0x8HJUd .node polygon,#mermaid-svg-iK9yB9hrM0x8HJUd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iK9yB9hrM0x8HJUd .rough-node .label text,#mermaid-svg-iK9yB9hrM0x8HJUd .node .label text,#mermaid-svg-iK9yB9hrM0x8HJUd .image-shape .label,#mermaid-svg-iK9yB9hrM0x8HJUd .icon-shape .label{text-anchor:middle;}#mermaid-svg-iK9yB9hrM0x8HJUd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iK9yB9hrM0x8HJUd .rough-node .label,#mermaid-svg-iK9yB9hrM0x8HJUd .node .label,#mermaid-svg-iK9yB9hrM0x8HJUd .image-shape .label,#mermaid-svg-iK9yB9hrM0x8HJUd .icon-shape .label{text-align:center;}#mermaid-svg-iK9yB9hrM0x8HJUd .node.clickable{cursor:pointer;}#mermaid-svg-iK9yB9hrM0x8HJUd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iK9yB9hrM0x8HJUd .arrowheadPath{fill:#333333;}#mermaid-svg-iK9yB9hrM0x8HJUd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iK9yB9hrM0x8HJUd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iK9yB9hrM0x8HJUd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iK9yB9hrM0x8HJUd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iK9yB9hrM0x8HJUd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iK9yB9hrM0x8HJUd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iK9yB9hrM0x8HJUd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iK9yB9hrM0x8HJUd .cluster text{fill:#333;}#mermaid-svg-iK9yB9hrM0x8HJUd .cluster span{color:#333;}#mermaid-svg-iK9yB9hrM0x8HJUd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iK9yB9hrM0x8HJUd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iK9yB9hrM0x8HJUd rect.text{fill:none;stroke-width:0;}#mermaid-svg-iK9yB9hrM0x8HJUd .icon-shape,#mermaid-svg-iK9yB9hrM0x8HJUd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iK9yB9hrM0x8HJUd .icon-shape p,#mermaid-svg-iK9yB9hrM0x8HJUd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iK9yB9hrM0x8HJUd .icon-shape .label rect,#mermaid-svg-iK9yB9hrM0x8HJUd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iK9yB9hrM0x8HJUd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iK9yB9hrM0x8HJUd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iK9yB9hrM0x8HJUd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 生产KPI体系
产量指标
生产KPI
质量指标
效率指标
能耗指标
1.2 核心KPI指标
| 指标 | 计算公式 | 说明 |
|---|---|---|
| 产量 | 合格品数量 | 生产总量 |
| 良品率 | 合格品/总产量 × 100% | 质量指标 |
| OEE | 可用率×性能率×良品率 | 综合效率 |
| 能耗 | 总能耗/产量 | 单位能耗 |
1.3 指标监控目标
| 目标 | 说明 |
|---|---|
| 实时性 | 指标实时计算 |
| 准确性 | 数据准确可靠 |
| 可视化 | 指标直观展示 |
| 告警性 | 异常及时告警 |
二、KPI定义与计算
2.1 KPI定义表
python
// KPI定义表
kpiDefinitions = table(
["production", "quality_rate", "oee", "energy_consumption"] as kpi_id,
["产量", "良品率", "OEE", "单位能耗"] as kpi_name,
["count(product_id)", "sum(qualified)/count(*)*100", "availability*performance*quality", "sum(energy)/count(product_id)"] as formula,
["件", "%", "%", "kWh/件"] as unit,
[1000, 95, 85, 10] as target
)
2.2 产量计算
python
// 产量数据表
share streamTable(100000:0,
`product_id`device_id`timestamp`quantity`qualified,
[SYMBOL, SYMBOL, TIMESTAMP, INT, BOOL]) as production_stream
// 实时产量统计
share table(1:0,
`time_window`device_id`production_count`qualified_count,
[TIMESTAMP, SYMBOL, LONG, LONG]) as production_agg
// 产量聚合引擎
productionEngine = createTimeSeriesEngine("production_engine", 60000,
<[count(*) as production_count,
sum(qualified) as qualified_count]>,
production_agg, `timestamp, `device_id)
subscribeTable(, "production_stream", "production_agg", -1, productionEngine, true)
2.3 良品率计算
python
// 良品率计算
def calculateQualityRate(deviceId, startTime, endTime) {
data = select count(*) as total,
sum(qualified) as qualified
from production_stream
where device_id = deviceId
and timestamp between startTime and endTime
if (data.total[0] == 0) {
return 0.0
}
return data.qualified[0] * 100.0 / data.total[0]
}
// 批量良品率
def batchQualityRate(startTime, endTime) {
return select device_id,
sum(qualified) * 100.0 / count(*) as quality_rate
from production_stream
where timestamp between startTime and endTime
group by device_id
}
2.4 OEE计算
python
// OEE数据表
share table(1:0,
`device_id`timestamp`availability`performance`quality,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as oee_data
// OEE计算
def calculateOEE(deviceId, startTime, endTime) {
// 可用率 = 实际运行时间 / 计划运行时间
availability = getAvailability(deviceId, startTime, endTime)
// 性能率 = 实际产量 / 理论产量
performance = getPerformance(deviceId, startTime, endTime)
// 质量率 = 合格品 / 总产量
quality = getQuality(deviceId, startTime, endTime)
// OEE = 可用率 × 性能率 × 质量率
oee = availability * performance * quality / 10000
insert into oee_data values (deviceId, now(), availability, performance, quality)
return oee
}
def getAvailability(deviceId, startTime, endTime) {
runTime = getRunTime(deviceId, startTime, endTime)
plannedTime = endTime - startTime
return runTime * 100.0 / plannedTime
}
def getPerformance(deviceId, startTime, endTime) {
actualOutput = getActualOutput(deviceId, startTime, endTime)
theoreticalOutput = getTheoreticalOutput(deviceId, startTime, endTime)
return actualOutput * 100.0 / theoreticalOutput
}
def getQuality(deviceId, startTime, endTime) {
return calculateQualityRate(deviceId, startTime, endTime)
}
三、实时统计
3.1 时间窗口统计
python
// 多时间窗口统计
def multiWindowStats(deviceId) {
now = now()
return dict(STRING, ANY, [
["hourly", calculateHourlyStats(deviceId, now - 3600000, now)],
["daily", calculateDailyStats(deviceId, now - 86400000, now)],
["weekly", calculateWeeklyStats(deviceId, now - 604800000, now)]
])
}
def calculateHourlyStats(deviceId, startTime, endTime) {
return select device_id,
count(*) as production,
sum(qualified) * 100.0 / count(*) as quality_rate
from production_stream
where device_id = deviceId
and timestamp between startTime and endTime
group by device_id
}
3.2 滑动窗口统计
python
// 滑动窗口统计
def slidingWindowStats(deviceId, windowSize = 3600000) {
now = now()
startTime = now - windowSize
return select device_id,
count(*) as production,
avg(production) as avg_production,
sum(qualified) * 100.0 / count(*) as quality_rate
from production_stream
where device_id = deviceId
and timestamp between startTime and now
group by device_id
}
3.3 实时聚合引擎
python
// 实时KPI聚合
share table(1:0,
`time_window`kpi_id`kpi_value,
[TIMESTAMP, STRING, DOUBLE]) as kpi_realtime
// KPI计算引擎
def kpiCalculateEngine() {
while (true) {
now = now()
// 计算各KPI
production = getProductionCount(now - 60000, now)
qualityRate = getQualityRate(now - 60000, now)
oee = getOEE(now - 60000, now)
// 写入实时表
insert into kpi_realtime values (now, "production", production)
insert into kpi_realtime values (now, "quality_rate", qualityRate)
insert into kpi_realtime values (now, "oee", oee)
sleep(60000)
}
}
submitJob("kpi_engine", "KPI计算引擎", kpiCalculateEngine)
四、趋势分析
4.1 趋势数据
python
// KPI趋势表
share table(1:0,
`time_window`kpi_id`kpi_value`trend,
[TIMESTAMP, STRING, DOUBLE, STRING]) as kpi_trend
// 趋势计算
def calculateTrend(kpiId, periods = 7) {
data = select * from kpi_realtime
where kpi_id = kpiId
order by time_window
limit periods
if (data.rows() < 2) {
return "stable"
}
first = data.kpi_value[0]
last = data.kpi_value[-1]
if (last > first * 1.05) {
return "up"
} else if (last < first * 0.95) {
return "down"
} else {
return "stable"
}
}
4.2 同比环比
python
// 同比环比计算
def calculateYoY(kpiId) {
now = now()
current = getKpiValue(kpiId, now - 86400000, now)
lastYear = getKpiValue(kpiId, now - 365*86400000, now - 364*86400000)
if (lastYear == 0) {
return 0.0
}
return (current - lastYear) * 100.0 / lastYear
}
def calculateMoM(kpiId) {
now = now()
current = getKpiValue(kpiId, now - 86400000, now)
lastMonth = getKpiValue(kpiId, now - 60*86400000, now - 59*86400000)
if (lastMonth == 0) {
return 0.0
}
return (current - lastMonth) * 100.0 / lastMonth
}
4.3 预测分析
python
// 简单移动平均预测
def predictKpi(kpiId, periods = 7) {
data = select * from kpi_realtime
where kpi_id = kpiId
order by time_window desc
limit periods
if (data.rows() == 0) {
return 0.0
}
return avg(data.kpi_value)
}
五、指标告警
5.1 告警规则
python
// KPI告警规则
kpiAlertRules = table(
["production_low", "quality_low", "oee_low"] as rule_name,
["production", "quality_rate", "oee"] as kpi_id,
[500, 90, 80] as threshold,
["<", "<", "<"] as operator,
[2, 1, 1] as alert_level
)
// 检查KPI告警
def checkKpiAlerts() {
alerts = array(STRING, 0)
for (rule in kpiAlertRules) {
value = getLatestKpi(rule.kpi_id)
if (eval(string(value) + rule.operator + string(rule.threshold))) {
alerts.append!(rule.rule_name + ": " + string(value))
}
}
return alerts
}
5.2 告警推送
python
// KPI告警推送
def pushKpiAlert(kpiId, value, threshold) {
message = "KPI告警: " + kpiId + " 当前值 " + string(value) + " 低于阈值 " + string(threshold)
// 记录告警
insert into alert_log values (now(), "system", kpiId, 2, value, message)
// 推送
print(message)
}
六、可视化展示
6.1 KPI看板数据
python
// KPI看板
def getKpiDashboard() {
now = now()
return dict(STRING, ANY, [
["production", getLatestKpi("production")],
["quality_rate", getLatestKpi("quality_rate")],
["oee", getLatestKpi("oee")],
["production_trend", calculateTrend("production")],
["quality_trend", calculateTrend("quality_rate")],
["oee_trend", calculateTrend("oee")]
])
}
def getLatestKpi(kpiId) {
return exec last(kpi_value) from kpi_realtime where kpi_id = kpiId
}
6.2 KPI排名
python
// 设备KPI排名
def getKpiRanking(kpiId, limit = 10) {
return select device_id,
kpi_value,
rank() over order by kpi_value desc as rank
from device_kpi
where kpi_id = kpiId
limit limit
}
七、实战案例
7.1 完整KPI监控系统
python
// ========== 生产KPI监控系统 ==========
// 1. 创建数据表
share streamTable(100000:0,
`product_id`device_id`timestamp`quantity`qualified,
[SYMBOL, SYMBOL, TIMESTAMP, INT, BOOL]) as production_stream
share table(1:0,
`time_window`kpi_id`kpi_value,
[TIMESTAMP, STRING, DOUBLE]) as kpi_realtime
share table(1:0,
`device_id`timestamp`availability`performance`quality`oee,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, DOUBLE]) as device_oee
// 2. 产量聚合引擎
share table(1:0,
`time_window`device_id`production_count`qualified_count,
[TIMESTAMP, SYMBOL, LONG, LONG]) as production_agg
productionEngine = createTimeSeriesEngine("production_engine", 60000,
<[count(*) as production_count,
sum(qualified) as qualified_count]>,
production_agg, `timestamp, `device_id)
subscribeTable(, "production_stream", "production_agg", -1, productionEngine, true)
// 3. KPI计算任务
def kpiCalculateTask() {
while (true) {
now = now()
// 计算产量
production = exec sum(production_count) from production_agg
where time_window > now - 60000
// 计算良品率
quality = exec sum(qualified_count) * 100.0 / sum(production_count)
from production_agg
where time_window > now - 60000
// 写入实时KPI
if (production.size() > 0) {
insert into kpi_realtime values (now, "production", production[0])
}
if (quality.size() > 0) {
insert into kpi_realtime values (now, "quality_rate", quality[0])
}
sleep(60000)
}
}
submitJob("kpi_calculate", "KPI计算", kpiCalculateTask)
// 4. 模拟数据
def generateMockProduction() {
while (true) {
data = table(
"P" + string(rand(1000, 10)) as product_id,
take(1..10, 10) as device_id,
take(now(), 10) as timestamp,
take(1, 10) as quantity,
rand([true, true, true, true, false], 10) as qualified
)
production_stream.append!(data)
sleep(5000)
}
}
submitJob("mock_production", "模拟数据", generateMockProduction)
// 5. KPI看板接口
def getKpiDashboard() {
return select * from kpi_realtime order by time_window desc limit 10
}
addFunctionView(getKpiDashboard)
print("生产KPI监控系统启动完成")
八、总结
本文详细介绍了DolphinDB生产指标监控:
- KPI定义:产量、良品率、OEE、能耗
- 指标计算:实时计算、批量计算
- 实时统计:时间窗口、滑动窗口、聚合引擎
- 趋势分析:趋势计算、同比环比、预测分析
- 指标告警:告警规则、告警推送
- 可视化展示:KPI看板、KPI排名
思考题:
- 如何设计灵活的KPI定义系统?
- 如何保证KPI计算的实时性?
- 如何实现KPI的自动预警?