目录
-
- 摘要
- 一、RANGE分区概述
-
- [1.1 什么是RANGE分区](#1.1 什么是RANGE分区)
- [1.2 RANGE分区特点](#1.2 RANGE分区特点)
- [1.3 适用场景](#1.3 适用场景)
- 二、创建RANGE分区
-
- [2.1 基本语法](#2.1 基本语法)
- [2.2 时间范围分区](#2.2 时间范围分区)
- [2.3 数值范围分区](#2.3 数值范围分区)
- [2.4 按月分区](#2.4 按月分区)
- 三、RANGE分区查询
-
- [3.1 范围查询优化](#3.1 范围查询优化)
- [3.2 时间窗口查询](#3.2 时间窗口查询)
- 四、动态分区管理
-
- [4.1 添加分区](#4.1 添加分区)
- [4.2 删除分区](#4.2 删除分区)
- [4.3 分区数据迁移](#4.3 分区数据迁移)
- 五、RANGE分区最佳实践
-
- [5.1 分区粒度选择](#5.1 分区粒度选择)
- [5.2 分区大小建议](#5.2 分区大小建议)
- [5.3 时间分区设计](#5.3 时间分区设计)
- 六、组合RANGE分区
-
- [6.1 时间+设备分区](#6.1 时间+设备分区)
- [6.2 时间+哈希分区](#6.2 时间+哈希分区)
- 七、实战案例
-
- [7.1 物联网数据按日分区](#7.1 物联网数据按日分区)
- [7.2 数据生命周期管理](#7.2 数据生命周期管理)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB RANGE分区策略。从RANGE分区原理到设计方法,从时间范围分区到数值范围分区,从动态分区到分区管理,全面介绍RANGE分区的应用场景和优化技巧。通过丰富的代码示例,帮助读者掌握RANGE分区设计和管理的核心技能。
一、RANGE分区概述
1.1 什么是RANGE分区
RANGE分区按照列值的范围进行分区,每个分区包含一个值域范围的数据:
RANGE分区原理
原始数据
按范围分区
分区1: 1-100
分区2: 101-200
分区3: 201-300
分区4: 301-400
1.2 RANGE分区特点
| 特点 | 说明 |
|---|---|
| 范围分区 | 按值域范围分区 |
| 顺序存储 | 数据按范围有序存储 |
| 适合连续值 | 适合时间、数值等 |
| 支持扩展 | 可动态添加新分区 |
1.3 适用场景
| 场景 | 说明 |
|---|---|
| 时间序列数据 | 按日期/时间范围分区 |
| 数值范围数据 | 按数值区间分区 |
| 历史数据管理 | 便于按时间归档 |
| 数据生命周期 | 便于冷热数据分离 |
二、创建RANGE分区
2.1 基本语法
python
// RANGE分区语法
db = database("dfs://db_name", RANGE, partition_vector)
// 参数说明:
// - partition_vector: 分区边界向量
// 例如 [1, 100, 200, 300] 表示三个分区:
// [1,100), [100,200), [200,300)
2.2 时间范围分区
python
// 按日期范围分区
dates = 2024.01.01..2024.12.31
db = database("dfs://time_db", RANGE, dates)
// 创建分区表
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `timestamp)
// 插入数据
t = table(
take(1..100, 10000) as device_id,
take(2024.01.01T00:00:00 + 0..9999 * 60000, 10000) as timestamp,
rand(20.0..30.0, 10000) as temperature,
rand(40.0..60.0, 10000) as humidity
)
loadTable("dfs://time_db", "sensor_data").append!(t)
2.3 数值范围分区
python
// 按数值范围分区
ranges = [0, 100, 200, 300, 400, 500]
db = database("dfs://range_db", RANGE, ranges)
// 创建分区表
schema = table(1:0,
`value_range`count`sum_val,
[INT, INT, DOUBLE])
db.createPartitionedTable(schema, `stats_data, `value_range)
// 插入数据
t = table(
rand(0..500, 1000) as value_range,
rand(1..10, 1000) as count,
rand(100.0..1000.0, 1000) as sum_val
)
loadTable("dfs://range_db", "stats_data").append!(t)
2.4 按月分区
python
// 按月分区
months = [2024.01M, 2024.02M, 2024.03M, 2024.04M, 2024.05M, 2024.06M,
2024.07M, 2024.08M, 2024.09M, 2024.10M, 2024.11M, 2024.12M, 2025.01M]
db = database("dfs://monthly_db", RANGE, months)
// 创建分区表
schema = table(1:0,
`month`device_id`value,
[MONTH, INT, DOUBLE])
db.createPartitionedTable(schema, `monthly_data, `month)
三、RANGE分区查询
3.1 范围查询优化
python
// RANGE分区支持高效的范围查询
t = loadTable("dfs://time_db", "sensor_data")
// 查询日期范围(分区裁剪)
select count(*) from t
where date(timestamp) between 2024.01.01 and 2024.01.31
// 查询单日数据
select count(*) from t
where date(timestamp) = 2024.01.15
// 查看执行计划
explain select * from t
where date(timestamp) between 2024.01.01 and 2024.01.07
3.2 时间窗口查询
python
// 时间窗口聚合
select bar(timestamp, 1h) as hour,
avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp
from t
where date(timestamp) = 2024.01.15
group by bar(timestamp, 1h)
四、动态分区管理
4.1 添加分区
python
// RANGE分区支持动态添加新分区
db = database("dfs://time_db")
// 添加新日期分区
addPartitions(db, [2025.01.01, 2025.02.01])
// 查看分区方案
db.partitionSchema()
4.2 删除分区
python
// 删除旧分区数据
db = database("dfs://time_db")
// 删除指定日期分区
dropPartition(db, [2023.01.01])
// 注意:删除分区会删除该分区的所有数据
4.3 分区数据迁移
python
// 数据迁移函数
def migrateOldData(dbPath, tableName, cutoffDate) {
db = database(dbPath)
t = loadTable(db, tableName)
// 查询需要迁移的数据
oldData = select * from t
where date(timestamp) < cutoffDate
// 写入归档库
archive_db = database("dfs://archive_db")
loadTable(archive_db, tableName).append!(oldData)
// 删除原数据
dates = distinct(date(oldData.timestamp))
for (d in dates) {
dropPartition(db, [d])
}
return oldData.rows()
}
// 执行迁移
migrateOldData("dfs://time_db", "sensor_data", 2024.01.01)
五、RANGE分区最佳实践
5.1 分区粒度选择
| 数据特点 | 建议粒度 | 说明 |
|---|---|---|
| 高频数据 | 按日/小时 | 减少单分区数据量 |
| 中频数据 | 按日/周 | 平衡分区数量 |
| 低频数据 | 按月/季 | 减少分区数量 |
| 历史数据 | 按月/年 | 便于归档管理 |
5.2 分区大小建议
| 建议 | 说明 |
|---|---|
| 单分区大小 | 1GB-10GB |
| 分区数量 | 不超过10000 |
| 数据均匀 | 各分区数据量相近 |
5.3 时间分区设计
python
// 方案1:按日分区(适合高频数据)
dates = 2024.01.01..2024.12.31
db = database("dfs://daily_db", RANGE, dates)
// 方案2:按月分区(适合中频数据)
months = 2024.01M..2025.01M
db = database("dfs://monthly_db", RANGE, months)
// 方案3:按年分区(适合低频数据)
years = [2020, 2021, 2022, 2023, 2024, 2025]
db = database("dfs://yearly_db", RANGE, years)
六、组合RANGE分区
6.1 时间+设备分区
python
// 组合分区:时间RANGE + 设备VALUE
db = database("dfs://combo_db", COMPO,
[RANGE, 2024.01.01..2024.12.31, // 时间范围分区
VALUE, 1..100]) // 设备值分区
// 创建分区表
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `timestamp`device_id)
6.2 时间+哈希分区
python
// 组合分区:时间RANGE + 设备HASH
db = database("dfs://combo_db2", COMPO,
[RANGE, 2024.01.01..2024.12.31, // 时间范围分区
HASH, [INT, 10]]) // 设备哈希分区(10个桶)
// 创建分区表
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `timestamp`device_id)
七、实战案例
7.1 物联网数据按日分区
python
// 创建按日分区的物联网数据库
dates = 2024.01.01..2024.12.31
db = database("dfs://iot_daily", RANGE, dates)
// 创建设备数据表
schema = table(1:0,
`device_id`timestamp`temperature`humidity`pressure`vibration`power,
[INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `device_data, `timestamp)
// 创建告警表
schema = table(1:0,
`alert_id`device_id`timestamp`alert_type`alert_level`message,
[LONG, INT, TIMESTAMP, SYMBOL, INT, STRING])
db.createPartitionedTable(schema, `alert_data, `timestamp)
// 模拟数据写入
def simulateData(startDate, days) {
for (i in 0..(days-1)) {
date = startDate + i
data = table(
take(1..100, 10000) as device_id,
take(dateT00:00:00 + 0..9999 * 8640, 10000) as timestamp,
rand(20.0..30.0, 10000) as temperature,
rand(40.0..60.0, 10000) as humidity,
rand(1000.0..1020.0, 10000) as pressure,
rand(0.0..5.0, 10000) as vibration,
rand(100.0..500.0, 10000) as power
)
loadTable("dfs://iot_daily", "device_data").append!(data)
}
}
simulateData(2024.01.01, 30) // 模拟30天数据
// 查询某日数据
select count(*) from loadTable("dfs://iot_daily", "device_data")
where date(timestamp) = 2024.01.15
7.2 数据生命周期管理
python
// 数据生命周期管理
def lifecycleManagement() {
db = database("dfs://iot_daily")
// 1. 归档90天前的数据
cutoffDate = today() - 90
oldData = select * from loadTable(db, "device_data")
where date(timestamp) < cutoffDate
archive_db = database("dfs://iot_archive")
loadTable(archive_db, "device_data").append!(oldData)
// 2. 删除已归档分区
dates = distinct(date(oldData.timestamp))
for (d in dates) {
dropPartition(db, [d])
}
// 3. 添加新分区(未来30天)
newDates = (today() + 1)..(today() + 30)
addPartitions(db, newDates)
print("生命周期管理完成")
}
// 每日执行
scheduleJob("lifecycle", "数据生命周期管理", lifecycleManagement,
02:00, 2024.01.01, 2030.12.31, 'D')
八、总结
本文详细介绍了DolphinDB RANGE分区策略:
- 分区原理:按值域范围分区
- 创建方法:时间范围、数值范围、按月分区
- 查询优化:范围查询、时间窗口查询
- 动态管理:添加分区、删除分区、数据迁移
- 最佳实践:分区粒度、分区大小、时间分区设计
- 组合分区:时间+设备、时间+哈希
思考题:
- RANGE分区适合什么类型的数据?
- 如何选择合适的分区粒度?
- 如何实现数据生命周期管理?