目录
-
- 摘要
- 一、流数据表概述
-
- [1.1 流数据表特点](#1.1 流数据表特点)
- [1.2 流表 vs 普通表](#1.2 流表 vs 普通表)
- 二、创建流数据表
-
- [2.1 基本创建](#2.1 基本创建)
- [2.2 指定容量](#2.2 指定容量)
- [2.3 创建带默认值的流表](#2.3 创建带默认值的流表)
- [2.4 查看流表结构](#2.4 查看流表结构)
- 三、流表订阅
-
- [3.1 基本订阅](#3.1 基本订阅)
- [3.2 订阅参数详解](#3.2 订阅参数详解)
- [3.3 多订阅者](#3.3 多订阅者)
- [3.4 取消订阅](#3.4 取消订阅)
- 四、处理函数
-
- [4.1 简单处理](#4.1 简单处理)
- [4.2 过滤处理](#4.2 过滤处理)
- [4.3 转换处理](#4.3 转换处理)
- [4.4 聚合处理](#4.4 聚合处理)
- [4.5 复杂处理](#4.5 复杂处理)
- 五、批量处理
-
- [5.1 批量处理配置](#5.1 批量处理配置)
- [5.2 批量处理优势](#5.2 批量处理优势)
- [5.3 批量处理最佳实践](#5.3 批量处理最佳实践)
- 六、流表持久化
-
- [6.1 启用持久化](#6.1 启用持久化)
- [6.2 持久化模式](#6.2 持久化模式)
- [6.3 持久化配置](#6.3 持久化配置)
- [6.4 持久化监控](#6.4 持久化监控)
- 七、流表高可用
-
- [7.1 高可用配置](#7.1 高可用配置)
- [7.2 故障恢复](#7.2 故障恢复)
- 八、实战案例
-
- [8.1 实时数据采集系统](#8.1 实时数据采集系统)
- 九、总结
- 参考资料
摘要
本文深入讲解DolphinDB流数据表的创建与订阅。从流表创建到订阅配置,从处理函数到批量处理,从持久化到高可用,全面介绍流数据表的核心操作。通过丰富的代码示例,帮助读者掌握流数据表管理的核心技能。
一、流数据表概述
1.1 流数据表特点
流数据表特点
实时写入
发布订阅
多订阅者
实时处理
核心功能
数据缓冲
持久化
高可用
1.2 流表 vs 普通表
| 特性 | 普通表 | 流表 |
|---|---|---|
| 写入 | 普通写入 | 实时写入 |
| 订阅 | 不支持 | 支持发布订阅 |
| 持久化 | 手动 | 自动持久化 |
| 容量 | 无限制 | 可配置容量 |
二、创建流数据表
2.1 基本创建
python
// 创建流数据表
share streamTable(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE]) as sensor_stream
// 参数说明:
// - 1:0 -> 初始容量:初始行数
// - `device_id`timestamp`temperature`humidity -> 列名
// - [INT, TIMESTAMP, DOUBLE, DOUBLE] -> 列类型
// - share -> 共享给所有会话
// - as sensor_stream -> 表名
2.2 指定容量
python
// 指定初始容量
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE]) as sensor_stream
// 容量说明:
// - 100000:0 -> 预分配100000行空间,初始0行
// - 预分配可以提高写入性能
2.3 创建带默认值的流表
python
// 创建带默认值的流表
share streamTable(10000:0,
`device_id`timestamp`temperature`humidity`status,
[INT, TIMESTAMP, DOUBLE, DOUBLE, SYMBOL]) as sensor_stream
// 写入时可以省略某些列
insert into sensor_stream (device_id, timestamp, temperature)
values (1, now(), 25.5)
// humidity和status使用默认值
2.4 查看流表结构
python
// 查看流表结构
schema(sensor_stream)
// 查看流表数据
select count(*) from sensor_stream
select top 100 * from sensor_stream
三、流表订阅
3.1 基本订阅
python
// 创建流表
share streamTable(1:0,
`device_id`timestamp`temperature,
[INT, TIMESTAMP, DOUBLE]) as sensor_stream
// 创建结果表
share table(1:0,
`device_id`timestamp`temperature,
[INT, TIMESTAMP, DOUBLE]) as result_table
// 订阅流表
subscribeTable(, "sensor_stream", "handler1", -1,
def(msg) {
result_table.append!(msg)
}, true)
// 参数说明:
// - 第一个参数: 数据库路径(流表为空)
// - "sensor_stream": 流表名
// - "handler1": 订阅名称
// - -1: offset,-1表示从最新开始
// - handler: 处理函数
// - true: batchSize,true表示批量处理
3.2 订阅参数详解
python
// 完整订阅参数
subscribeTable(
"", // database: 数据库路径
"sensor_stream", // tableName: 流表名
"handler1", // actionName: 订阅名称
-1, // offset: 起始位置
handler, // handler: 处理函数
true, // batchSize: 批量处理
1000, // throttle: 节流时间(ms)
true, // hash: 是否哈希分组
10, // filter: 过滤条件
true // reconnect: 是否自动重连
)
// offset参数说明:
// - -1: 从最新数据开始
// - 0: 从头开始
// - N: 从第N条开始
3.3 多订阅者
python
// 创建多个订阅者
// 订阅者1:实时数据
subscribeTable(, "sensor_stream", "realtime_handler", -1,
def(msg) {
realtime_table.append!(msg)
}, true)
// 订阅者2:告警检测
subscribeTable(, "sensor_stream", "alert_handler", -1,
def(msg) {
alerts = select * from msg where temperature > 30
alert_table.append!(alerts)
}, true)
// 订阅者3:数据持久化
subscribeTable(, "sensor_stream", "persist_handler", -1,
def(msg) {
loadTable("dfs://db", "sensor_data").append!(msg)
}, true, 10000, true)
3.4 取消订阅
python
// 查看订阅状态
getSubscriptionStat()
// 取消指定订阅
unsubscribeTable(, "sensor_stream", "handler1")
// 取消流表的所有订阅
unsubscribeTable(, "sensor_stream")
// 取消所有订阅
unsubscribeAll()
四、处理函数
4.1 简单处理
python
// 简单处理:直接写入
def simpleHandler(msg) {
result_table.append!(msg)
}
subscribeTable(, "sensor_stream", "simple", -1, simpleHandler, true)
4.2 过滤处理
python
// 过滤处理
def filterHandler(msg) {
filtered = select * from msg
where temperature between 20 and 30
result_table.append!(filtered)
}
subscribeTable(, "sensor_stream", "filter", -1, filterHandler, true)
4.3 转换处理
python
// 转换处理
def transformHandler(msg) {
transformed = select device_id,
timestamp,
temperature,
temperature * 1.8 + 32 as fahrenheit,
humidity
from msg
result_table.append!(transformed)
}
subscribeTable(, "sensor_stream", "transform", -1, transformHandler, true)
4.4 聚合处理
python
// 聚合处理
def aggHandler(msg) {
agg = select device_id,
avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as cnt
from msg
group by device_id
agg_result.append!(agg)
}
subscribeTable(, "sensor_stream", "agg", -1, aggHandler, true)
4.5 复杂处理
python
// 复杂处理:多步骤
def complexHandler(msg) {
// 步骤1:数据清洗
cleaned = select * from msg
where temperature is not null
and temperature between -40 and 100
// 步骤2:数据转换
transformed = select device_id,
timestamp,
temperature,
case when temperature > 30 then "高温"
when temperature < 10 then "低温"
else "正常" end as status
from cleaned
// 步骤3:写入结果
result_table.append!(transformed)
// 步骤4:触发告警
alerts = select * from transformed where status != "正常"
alert_table.append!(alerts)
}
subscribeTable(, "sensor_stream", "complex", -1, complexHandler, true)
五、批量处理
5.1 批量处理配置
python
// 批量处理:累积一定数量后处理
subscribeTable(, "sensor_stream", "batch_handler", -1,
def(msg) {
result_table.append!(msg)
},
1000) // batchSize=1000,累积1000条后处理
// 批量处理 + 节流
subscribeTable(, "sensor_stream", "batch_throttle_handler", -1,
def(msg) {
result_table.append!(msg)
},
1000, // batchSize=1000
5000) // throttle=5000ms,最多等待5秒
5.2 批量处理优势
| 优势 | 说明 |
|---|---|
| 减少IO | 批量写入减少IO次数 |
| 提高吞吐 | 批量处理提高吞吐量 |
| 降低延迟 | 合理配置降低延迟 |
5.3 批量处理最佳实践
python
// 最佳实践:根据场景选择批量大小
// 高吞吐场景:batchSize=10000
subscribeTable(, "sensor_stream", "high_throughput", -1,
def(msg) { result_table.append!(msg) }, 10000)
// 低延迟场景:batchSize=100
subscribeTable(, "sensor_stream", "low_latency", -1,
def(msg) { result_table.append!(msg) }, 100)
// 平衡场景:batchSize=1000, throttle=1000ms
subscribeTable(, "sensor_stream", "balanced", -1,
def(msg) { result_table.append!(msg) }, 1000, 1000)
六、流表持久化
6.1 启用持久化
python
// 启用持久化
enableTablePersistence(sensor_stream, true, true, 1000000)
// 参数说明:
// - async=true: 异步持久化
// - sync=true: 同步持久化(高可靠)
// - capacity=1000000: 内存中保留的最大行数
6.2 持久化模式
| 模式 | 说明 | 适用场景 |
|---|---|---|
| async=true | 异步持久化 | 高吞吐 |
| sync=true | 同步持久化 | 高可靠 |
| async+sync | 双重持久化 | 最高可靠 |
6.3 持久化配置
python
// 高吞吐配置
enableTablePersistence(sensor_stream, true, false, 1000000)
// 高可靠配置
enableTablePersistence(sensor_stream, false, true, 1000000)
// 平衡配置
enableTablePersistence(sensor_stream, true, true, 1000000)
6.4 持久化监控
python
// 查看持久化状态
getPersistenceStat()
// 查看持久化文件
persistenceDir()
七、流表高可用
7.1 高可用配置
python
// 高可用流表配置
// 1. 启用持久化
enableTablePersistence(sensor_stream, true, true, 1000000)
// 2. 订阅配置自动重连
subscribeTable(, "sensor_stream", "ha_handler", -1,
def(msg) { result_table.append!(msg) },
true, 1000, false, , true) // reconnect=true
// 3. 监控订阅状态
def monitorSubscription() {
stat = getSubscriptionStat()
for (row in stat) {
if (row.status != "OK") {
print("订阅异常: " + row.actionName)
}
}
}
7.2 故障恢复
python
// 故障恢复流程
def recoverStream() {
// 1. 检查流表状态
stat = getStreamStat()
// 2. 重新创建流表(如果需要)
if (stat.rows() == 0) {
share streamTable(1:0,
`device_id`timestamp`temperature,
[INT, TIMESTAMP, DOUBLE]) as sensor_stream
enableTablePersistence(sensor_stream, true, true, 1000000)
}
// 3. 重新订阅
subscribeTable(, "sensor_stream", "handler", -1,
def(msg) { result_table.append!(msg) }, true)
print("流表恢复完成")
}
八、实战案例
8.1 实时数据采集系统
python
// ========== 1. 创建流表 ==========
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity`pressure,
[INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as sensor_stream
// ========== 2. 启用持久化 ==========
enableTablePersistence(sensor_stream, true, true, 1000000)
// ========== 3. 创建分布式表 ==========
db = database("dfs://realtime_db", VALUE, 1..100)
schema = table(1:0, `device_id`timestamp`temperature`humidity`pressure,
[INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `device_id)
// ========== 4. 创建订阅 ==========
// 实时数据订阅
share table(1:0,
`device_id`timestamp`temperature`humidity`pressure,
[INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as realtime_data
subscribeTable(, "sensor_stream", "realtime", -1,
def(msg) { realtime_data.append!(msg) }, true)
// 持久化订阅
subscribeTable(, "sensor_stream", "persist", -1,
def(msg) {
loadTable("dfs://realtime_db", "sensor_data").append!(msg)
}, 10000, 5000)
// 告警订阅
share table(1:0,
`device_id`timestamp`alert_type`value,
[INT, TIMESTAMP, SYMBOL, DOUBLE]) as alert_table
subscribeTable(, "sensor_stream", "alert", -1,
def(msg) {
alerts = select device_id, timestamp,
`temperature_high as alert_type,
temperature as value
from msg
where temperature > 30
alert_table.append!(alerts)
}, true)
// ========== 5. 监控函数 ==========
def monitorStream() {
print("=== 流表监控 ===")
print("流表行数: " + string(exec count(*) from sensor_stream))
print("实时数据行数: " + string(exec count(*) from realtime_data))
print("告警数量: " + string(exec count(*) from alert_table))
stat = getSubscriptionStat()
print("订阅状态: " + string(stat.rows()) + " 个订阅")
}
monitorStream()
print("实时数据采集系统创建完成")
九、总结
本文详细介绍了DolphinDB流数据表的创建与订阅:
- 流表创建:基本创建、指定容量、查看结构
- 流表订阅:基本订阅、参数配置、多订阅者
- 处理函数:简单、过滤、转换、聚合处理
- 批量处理:批量配置、优势分析、最佳实践
- 流表持久化:启用持久化、模式选择、监控
- 高可用:配置、故障恢复
思考题:
- 如何选择合适的批量大小?
- 流表持久化有什么作用?
- 如何设计高可用的流处理系统?