目录
-
- 摘要
- 一、横截面引擎概述
-
- [1.1 什么是横截面引擎](#1.1 什么是横截面引擎)
- [1.2 横截面引擎 vs 时间序列引擎](#1.2 横截面引擎 vs 时间序列引擎)
- [1.3 适用场景](#1.3 适用场景)
- 二、创建横截面引擎
-
- [2.1 基本语法](#2.1 基本语法)
- [2.2 创建简单引擎](#2.2 创建简单引擎)
- [2.3 创建带分组的引擎](#2.3 创建带分组的引擎)
- 三、触发模式
-
- [3.1 触发模式类型](#3.1 触发模式类型)
- [3.2 每行触发](#3.2 每行触发)
- [3.3 定时触发](#3.3 定时触发)
- 四、聚合指标
-
- [4.1 基本统计](#4.1 基本统计)
- [4.2 百分位统计](#4.2 百分位统计)
- [4.3 Top-N计算](#4.3 Top-N计算)
- 五、实战案例
-
- [5.1 设备实时排名](#5.1 设备实时排名)
- [5.2 实时异常检测](#5.2 实时异常检测)
- [5.3 生产效率监控](#5.3 生产效率监控)
- 六、引擎管理
-
- [6.1 查看引擎状态](#6.1 查看引擎状态)
- [6.2 删除引擎](#6.2 删除引擎)
- [6.3 引擎监控](#6.3 引擎监控)
- 七、性能优化
-
- [7.1 分组数量优化](#7.1 分组数量优化)
- [7.2 触发模式选择](#7.2 触发模式选择)
- [7.3 内存管理](#7.3 内存管理)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB横截面引擎。从引擎原理到创建配置,从实时统计到Top-N计算,从分组分析到性能优化,全面介绍横截面引擎的核心功能。通过丰富的代码示例,帮助读者掌握实时统计分析的核心技能。
一、横截面引擎概述
1.1 什么是横截面引擎
横截面引擎是对同一时刻所有分组的数据进行聚合计算:
#mermaid-svg-kD05TWvTcQCqlkct{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-kD05TWvTcQCqlkct .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kD05TWvTcQCqlkct .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kD05TWvTcQCqlkct .error-icon{fill:#552222;}#mermaid-svg-kD05TWvTcQCqlkct .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kD05TWvTcQCqlkct .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kD05TWvTcQCqlkct .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kD05TWvTcQCqlkct .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kD05TWvTcQCqlkct .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kD05TWvTcQCqlkct .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kD05TWvTcQCqlkct .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kD05TWvTcQCqlkct .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kD05TWvTcQCqlkct .marker.cross{stroke:#333333;}#mermaid-svg-kD05TWvTcQCqlkct svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kD05TWvTcQCqlkct p{margin:0;}#mermaid-svg-kD05TWvTcQCqlkct .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kD05TWvTcQCqlkct .cluster-label text{fill:#333;}#mermaid-svg-kD05TWvTcQCqlkct .cluster-label span{color:#333;}#mermaid-svg-kD05TWvTcQCqlkct .cluster-label span p{background-color:transparent;}#mermaid-svg-kD05TWvTcQCqlkct .label text,#mermaid-svg-kD05TWvTcQCqlkct span{fill:#333;color:#333;}#mermaid-svg-kD05TWvTcQCqlkct .node rect,#mermaid-svg-kD05TWvTcQCqlkct .node circle,#mermaid-svg-kD05TWvTcQCqlkct .node ellipse,#mermaid-svg-kD05TWvTcQCqlkct .node polygon,#mermaid-svg-kD05TWvTcQCqlkct .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kD05TWvTcQCqlkct .rough-node .label text,#mermaid-svg-kD05TWvTcQCqlkct .node .label text,#mermaid-svg-kD05TWvTcQCqlkct .image-shape .label,#mermaid-svg-kD05TWvTcQCqlkct .icon-shape .label{text-anchor:middle;}#mermaid-svg-kD05TWvTcQCqlkct .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kD05TWvTcQCqlkct .rough-node .label,#mermaid-svg-kD05TWvTcQCqlkct .node .label,#mermaid-svg-kD05TWvTcQCqlkct .image-shape .label,#mermaid-svg-kD05TWvTcQCqlkct .icon-shape .label{text-align:center;}#mermaid-svg-kD05TWvTcQCqlkct .node.clickable{cursor:pointer;}#mermaid-svg-kD05TWvTcQCqlkct .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kD05TWvTcQCqlkct .arrowheadPath{fill:#333333;}#mermaid-svg-kD05TWvTcQCqlkct .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kD05TWvTcQCqlkct .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kD05TWvTcQCqlkct .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kD05TWvTcQCqlkct .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kD05TWvTcQCqlkct .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kD05TWvTcQCqlkct .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kD05TWvTcQCqlkct .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kD05TWvTcQCqlkct .cluster text{fill:#333;}#mermaid-svg-kD05TWvTcQCqlkct .cluster span{color:#333;}#mermaid-svg-kD05TWvTcQCqlkct 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-kD05TWvTcQCqlkct .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kD05TWvTcQCqlkct rect.text{fill:none;stroke-width:0;}#mermaid-svg-kD05TWvTcQCqlkct .icon-shape,#mermaid-svg-kD05TWvTcQCqlkct .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kD05TWvTcQCqlkct .icon-shape p,#mermaid-svg-kD05TWvTcQCqlkct .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kD05TWvTcQCqlkct .icon-shape .label rect,#mermaid-svg-kD05TWvTcQCqlkct .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kD05TWvTcQCqlkct .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kD05TWvTcQCqlkct .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kD05TWvTcQCqlkct :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 横截面引擎
时刻T
设备1数据
设备2数据
设备3数据
横截面聚合
整体统计结果
1.2 横截面引擎 vs 时间序列引擎
| 特性 | 时间序列引擎 | 横截面引擎 |
|---|---|---|
| 聚合维度 | 时间窗口内 | 同一时刻所有分组 |
| 输出频率 | 窗口结束 | 每条数据触发 |
| 适用场景 | 时间趋势 | 实时排名、整体统计 |
1.3 适用场景
| 场景 | 说明 |
|---|---|
| 实时排名 | 设备实时排名 |
| 整体统计 | 所有设备整体统计 |
| Top-N计算 | 实时Top-N |
| 异常检测 | 整体异常检测 |
二、创建横截面引擎
2.1 基本语法
python
// 创建横截面引擎
agg = createCrossSectionalEngine(
"engine_name", // 引擎名称
metrics, // 聚合指标
outputTable, // 输出表
timeColumn, // 时间列
[keyColumn], // 分组列(可选)
[triggeringPattern], // 触发模式
[triggeringInterval] // 触发间隔
)
2.2 创建简单引擎
python
// 创建输入流表
share streamTable(1:0,
`device_id`timestamp`temperature,
[INT, TIMESTAMP, DOUBLE]) as input_stream
// 创建输出表
share table(1:0,
`timestamp`avg_temp`max_temp`min_temp`device_count,
[TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, LONG]) as output_table
// 创建横截面引擎
agg = createCrossSectionalEngine("cs_engine",
<[avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as device_count]>,
output_table, `timestamp)
// 订阅流表
subscribeTable(, "input_stream", "cs_agg", -1, agg, true)
2.3 创建带分组的引擎
python
// 创建带分组的横截面引擎
agg = createCrossSectionalEngine("grouped_cs_engine",
<[avg(temperature) as avg_temp,
max(temperature) as max_temp]>,
output_table, `timestamp, `device_id)
// 分组说明:
// - 每个device_id维护最新值
// - 聚合计算所有device_id的最新值
三、触发模式
3.1 触发模式类型
| 模式 | 说明 |
|---|---|
| perRow | 每条数据触发 |
| perBatch | 每批数据触发 |
| interval | 定时触发 |
3.2 每行触发
python
// 每行触发:每条数据都触发计算
agg = createCrossSectionalEngine("per_row_engine",
<[avg(temperature) as avg_temp]>,
output_table, `timestamp, `device_id,
"perRow") // 每行触发
3.3 定时触发
python
// 定时触发:每隔N毫秒触发
agg = createCrossSectionalEngine("interval_engine",
<[avg(temperature) as avg_temp]>,
output_table, `timestamp, `device_id,
"interval", 1000) // 每1秒触发
四、聚合指标
4.1 基本统计
python
// 基本统计指标
agg = createCrossSectionalEngine("basic_stats",
<[avg(temperature) as avg_temp,
sum(temperature) as sum_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as device_count,
std(temperature) as std_temp]>,
output_table, `timestamp, `device_id)
4.2 百分位统计
python
// 百分位统计
agg = createCrossSectionalEngine("percentile_stats",
<[percentile(temperature, 50) as median,
percentile(temperature, 95) as p95,
percentile(temperature, 99) as p99]>,
output_table, `timestamp, `device_id)
4.3 Top-N计算
python
// Top-N计算:需要自定义函数
// 使用top函数获取Top-N
// 创建输出表
share table(1:0,
`timestamp`top_devices`top_temps,
[TIMESTAMP, STRING, STRING]) as topn_table
// 创建引擎
agg = createCrossSectionalEngine("topn_engine",
<[concat(string(device_id), ",") as top_devices,
concat(string(temperature), ",") as top_temps]>,
topn_table, `timestamp, `device_id)
五、实战案例
5.1 设备实时排名
python
// ========== 1. 创建流表 ==========
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE]) as sensor_stream
// ========== 2. 创建输出表 ==========
share table(1:0,
`timestamp`avg_temp`max_temp`min_temp`device_count`std_temp,
[TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, LONG, DOUBLE]) as stats_table
// ========== 3. 创建横截面引擎 ==========
agg = createCrossSectionalEngine("ranking_engine",
<[avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as device_count,
std(temperature) as std_temp]>,
stats_table, `timestamp, `device_id,
"interval", 5000) // 每5秒输出
// ========== 4. 订阅流表 ==========
subscribeTable(, "sensor_stream", "ranking_agg", -1, agg, true)
// ========== 5. 模拟数据 ==========
def simulateRanking() {
for (i in 1..100) {
sensor_stream.append!(
table(
1..100 as device_id,
take(now(), 100) as timestamp,
rand(20.0..30.0, 100) as temperature,
rand(40.0..60.0, 100) as humidity
)
)
sleep(1000)
}
}
simulateRanking()
// 查看结果
select top 20 * from stats_table
5.2 实时异常检测
python
// ========== 1. 创建流表 ==========
share streamTable(100000:0,
`device_id`timestamp`temperature,
[INT, TIMESTAMP, DOUBLE]) as sensor_stream
// ========== 2. 创建输出表 ==========
share table(1:0,
`timestamp`avg_temp`std_temp`threshold`anomaly_count,
[TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, LONG]) as anomaly_table
// ========== 3. 创建异常检测引擎 ==========
agg = createCrossSectionalEngine("anomaly_engine",
<[avg(temperature) as avg_temp,
std(temperature) as std_temp,
avg(temperature) + 3 * std(temperature) as threshold,
sum(iif(temperature > avg(temperature) + 3 * std(temperature), 1, 0)) as anomaly_count]>,
anomaly_table, `timestamp, `device_id,
"interval", 10000) // 每10秒检测
// ========== 4. 订阅流表 ==========
subscribeTable(, "sensor_stream", "anomaly_agg", -1, agg, true)
5.3 生产效率监控
python
// ========== 1. 创建流表 ==========
share streamTable(100000:0,
`production_line`timestamp`output`efficiency,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE]) as production_stream
// ========== 2. 创建输出表 ==========
share table(1:0,
`timestamp`total_output`avg_efficiency`max_efficiency`line_count,
[TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, LONG]) as production_stats
// ========== 3. 创建监控引擎 ==========
agg = createCrossSectionalEngine("production_engine",
<[sum(output) as total_output,
avg(efficiency) as avg_efficiency,
max(efficiency) as max_efficiency,
count(*) as line_count]>,
production_stats, `timestamp, `production_line,
"interval", 60000) // 每分钟统计
// ========== 4. 订阅流表 ==========
subscribeTable(, "production_stream", "production_agg", -1, agg, true)
六、引擎管理
6.1 查看引擎状态
python
// 查看所有引擎状态
getStreamEngineStat()
// 查看特定引擎
getStreamEngineStat("cs_engine")
6.2 删除引擎
python
// 删除引擎
dropStreamEngine("cs_engine")
6.3 引擎监控
python
// 引擎监控函数
def monitorCSEngine() {
stat = getStreamEngineStat()
for (row in stat) {
if (row.type == "CrossSectionalAggregator") {
print("横截面引擎: " + row.name)
print(" 状态: " + row.status)
print(" 分组数: " + string(row.numGroups))
print(" 处理行数: " + string(row.processedRows))
}
}
}
monitorCSEngine()
七、性能优化
7.1 分组数量优化
python
// 分组数量建议
// 单引擎分组数 < 100000
// 如果分组数过多:
// 1. 使用多个引擎
// 2. 增加触发间隔
7.2 触发模式选择
| 场景 | 推荐触发模式 |
|---|---|
| 实时监控 | perRow |
| 周期统计 | interval |
| 批量处理 | perBatch |
7.3 内存管理
python
// 横截面引擎内存使用
// = 分组数 × 每组数据大小
// 优化:
// 1. 减少分组数
// 2. 使用过滤条件
// 3. 定期清理不活跃分组
八、总结
本文详细介绍了DolphinDB横截面引擎:
- 引擎原理:同一时刻所有分组聚合
- 创建方法:简单引擎、分组引擎
- 触发模式:每行触发、定时触发
- 聚合指标:基本统计、百分位、Top-N
- 实战应用:实时排名、异常检测、效率监控
- 性能优化:分组数量、触发模式、内存管理
思考题:
- 横截面引擎和时间序列引擎有什么区别?
- 如何选择合适的触发模式?
- 如何设计实时排名系统?