目录
-
- 摘要
- 一、VALUE分区概述
-
- [1.1 什么是VALUE分区](#1.1 什么是VALUE分区)
- [1.2 VALUE分区特点](#1.2 VALUE分区特点)
- [1.3 适用场景](#1.3 适用场景)
- 二、创建VALUE分区
-
- [2.1 基本语法](#2.1 基本语法)
- [2.2 创建单列VALUE分区](#2.2 创建单列VALUE分区)
- [2.3 创建字符串VALUE分区](#2.3 创建字符串VALUE分区)
- [2.4 创建日期VALUE分区](#2.4 创建日期VALUE分区)
- 三、VALUE分区查询
-
- [3.1 分区裁剪](#3.1 分区裁剪)
- [3.2 查询优化](#3.2 查询优化)
- 四、VALUE分区管理
-
- [4.1 添加分区](#4.1 添加分区)
- [4.2 查看分区](#4.2 查看分区)
- [4.3 分区统计](#4.3 分区统计)
- 五、VALUE分区最佳实践
-
- [5.1 分区列选择](#5.1 分区列选择)
- [5.2 分区数量建议](#5.2 分区数量建议)
- [5.3 分区设计示例](#5.3 分区设计示例)
- [六、VALUE分区 vs 其他分区](#六、VALUE分区 vs 其他分区)
-
- [6.1 对比表](#6.1 对比表)
- [6.2 选择建议](#6.2 选择建议)
- 七、实战案例
-
- [7.1 工厂设备数据分区](#7.1 工厂设备数据分区)
- [7.2 多租户数据分区](#7.2 多租户数据分区)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB VALUE分区策略。从VALUE分区原理到设计方法,从单列分区到多列分区,从分区管理到最佳实践,全面介绍VALUE分区的应用场景和优化技巧。通过丰富的代码示例,帮助读者掌握VALUE分区设计和管理的核心技能。
一、VALUE分区概述
1.1 什么是VALUE分区
VALUE分区是DolphinDB中最常用的分区策略之一,按照列值的枚举值进行分区:
VALUE分区原理
原始数据
按列值分区
分区1: 值=A
分区2: 值=B
分区3: 值=C
分区4: 值=D
1.2 VALUE分区特点
| 特点 | 说明 |
|---|---|
| 枚举分区 | 按列值的枚举值分区 |
| 精确匹配 | 查询时精确匹配分区 |
| 适合离散值 | 适合设备ID、地区等 |
| 分区数量固定 | 分区数等于枚举值数量 |
1.3 适用场景
| 场景 | 说明 |
|---|---|
| 设备数据 | 按设备ID分区 |
| 地区数据 | 按地区/城市分区 |
| 类型数据 | 按数据类型分区 |
| 状态数据 | 按状态值分区 |
二、创建VALUE分区
2.1 基本语法
python
// VALUE分区语法
db = database("dfs://db_name", VALUE, partition_column)
// 参数说明:
// - db_name: 数据库名称
// - VALUE: 分区类型
// - partition_column: 分区列(可以是向量或列名)
2.2 创建单列VALUE分区
python
// 按设备ID分区
device_ids = 1..100
db = database("dfs://device_db", VALUE, device_ids)
// 查看分区方案
db.schema()
// 创建分区表
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `device_id)
// 插入数据
t = table(
take(1..100, 1000) as device_id,
take(now(), 1000) as timestamp,
rand(20.0..30.0, 1000) as temperature,
rand(40.0..60.0, 1000) as humidity
)
loadTable("dfs://device_db", "sensor_data").append!(t)
2.3 创建字符串VALUE分区
python
// 按地区分区
regions = `北京`上海`广州`深圳`杭州`成都`武汉`西安
db = database("dfs://region_db", VALUE, regions)
// 创建分区表
schema = table(1:0,
`region`timestamp`sales`quantity,
[SYMBOL, TIMESTAMP, DOUBLE, INT])
db.createPartitionedTable(schema, `sales_data, `region)
// 插入数据
t = table(
take(regions, 1000) as region,
take(now(), 1000) as timestamp,
rand(1000.0..10000.0, 1000) as sales,
rand(10..100, 1000) as quantity
)
loadTable("dfs://region_db", "sales_data").append!(t)
2.4 创建日期VALUE分区
python
// 按日期分区
dates = 2024.01.01..2024.12.31
db = database("dfs://date_db", VALUE, dates)
// 创建分区表
schema = table(1:0,
`date`device_id`value,
[DATE, INT, DOUBLE])
db.createPartitionedTable(schema, `daily_data, `date)
三、VALUE分区查询
3.1 分区裁剪
python
// VALUE分区支持精确的分区裁剪
t = loadTable("dfs://device_db", "sensor_data")
// 查询单个设备(只扫描一个分区)
select count(*) from t where device_id = 1
// 查询多个设备(只扫描相关分区)
select count(*) from t where device_id in [1, 2, 3]
// 查看执行计划
explain select * from t where device_id = 1
3.2 查询优化
python
// 分区列过滤(高效)
select * from t where device_id = 1
// 非分区列过滤(全表扫描)
select * from t where temperature > 25
// 组合条件
select * from t where device_id = 1 and temperature > 25
四、VALUE分区管理
4.1 添加分区
python
// VALUE分区需要预先定义所有值
// 如果数据包含未定义的分区值,会报错
// 解决方案:创建数据库时包含所有可能的值
device_ids = 1..1000 // 预留足够的设备ID
db = database("dfs://device_db", VALUE, device_ids)
4.2 查看分区
python
// 查看分区列表
db = database("dfs://device_db")
db.partitionSchema()
// 查看分区数据量
select device_id, count(*) as cnt
from loadTable("dfs://device_db", "sensor_data")
group by device_id
4.3 分区统计
python
// 查看各分区大小
getTabletsMeta("dfs://device_db", "sensor_data")
// 分区数据分布
select device_id,
count(*) as record_count,
min(timestamp) as min_time,
max(timestamp) as max_time
from loadTable("dfs://device_db", "sensor_data")
group by device_id
order by record_count desc
五、VALUE分区最佳实践
5.1 分区列选择
| 选择原则 | 说明 |
|---|---|
| 高基数列 | 分区值不宜过多(<10000) |
| 查询频繁 | 经常作为查询条件 |
| 分布均匀 | 数据在各分区分布均匀 |
| 值稳定 | 分区值不会频繁变化 |
5.2 分区数量建议
| 场景 | 建议分区数 |
|---|---|
| 小集群 | 100-1000 |
| 中集群 | 1000-10000 |
| 大集群 | 10000-100000 |
5.3 分区设计示例
python
// 设备数据分区设计
// 方案1:按设备ID分区(设备数<10000)
db = database("dfs://device_db", VALUE, 1..10000)
// 方案2:按设备类型+ID组合分区(设备数>10000)
// 使用COMPO分区:先按类型,再按ID范围
db = database("dfs://device_db2", COMPO,
[VALUE, `typeA`typeB`typeC, RANGE, 1..1001])
// 方案3:按时间+设备分区(海量设备)
db = database("dfs://device_db3", COMPO,
[RANGE, 2024.01.01..2024.12.31, HASH, [INT, 100]])
六、VALUE分区 vs 其他分区
6.1 对比表
| 特性 | VALUE | RANGE | HASH |
|---|---|---|---|
| 分区方式 | 枚举值 | 范围 | 哈希 |
| 查询效率 | 精确匹配 | 范围查询 | 均匀分布 |
| 分区数量 | 固定 | 可扩展 | 固定 |
| 适用场景 | 离散值 | 连续值 | 均匀分布 |
6.2 选择建议
离散值
枚举类型
连续值
时间/数值
均匀分布
高基数
多维度
选择分区策略
数据特点
VALUE分区
RANGE分区
HASH分区
COMPO组合分区
七、实战案例
7.1 工厂设备数据分区
python
// 创建按车间分区的数据库
workshops = `车间A`车间B`车间C`车间D`车间E
db = database("dfs://factory_db", VALUE, workshops)
// 创建分区表
schema = table(1:0,
`workshop`device_id`timestamp`temperature`humidity`power,
[SYMBOL, INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `device_data, `workshop)
// 插入数据
t = table(
take(workshops, 10000) as workshop,
take(1..100, 10000) as device_id,
take(now() - 0..9999 * 1000, 10000) as timestamp,
rand(20.0..30.0, 10000) as temperature,
rand(40.0..60.0, 10000) as humidity,
rand(100.0..500.0, 10000) as power
)
loadTable("dfs://factory_db", "device_data").append!(t)
// 查询某车间数据
select * from loadTable("dfs://factory_db", "device_data")
where workshop = `车间A`
limit 10
7.2 多租户数据分区
python
// 创建按租户分区的数据库
tenants = `tenant_001`tenant_002`tenant_003`tenant_004`tenant_005
db = database("dfs://tenant_db", VALUE, tenants)
// 创建分区表
schema = table(1:0,
`tenant_id`user_id`timestamp`action`resource,
[SYMBOL, STRING, TIMESTAMP, SYMBOL, STRING])
db.createPartitionedTable(schema, `audit_log, `tenant_id)
// 查询某租户日志
select * from loadTable("dfs://tenant_db", "audit_log")
where tenant_id = `tenant_001`
and timestamp > now() - 86400000
八、总结
本文详细介绍了DolphinDB VALUE分区策略:
- 分区原理:按列值的枚举值分区
- 创建方法:单列分区、字符串分区、日期分区
- 查询优化:分区裁剪、精确匹配
- 分区管理:添加分区、查看分区、统计分区
- 最佳实践:分区列选择、分区数量建议
- 对比选择:VALUE vs RANGE vs HASH
思考题:
- VALUE分区适合什么类型的数据?
- 如何确定VALUE分区的分区数量?
- VALUE分区查询时如何实现分区裁剪?