目录
-
- 摘要
- 一、HASH分区概述
-
- [1.1 什么是HASH分区](#1.1 什么是HASH分区)
- [1.2 HASH分区特点](#1.2 HASH分区特点)
- [1.3 适用场景](#1.3 适用场景)
- 二、创建HASH分区
-
- [2.1 基本语法](#2.1 基本语法)
- [2.2 创建INT类型HASH分区](#2.2 创建INT类型HASH分区)
- [2.3 创建STRING类型HASH分区](#2.3 创建STRING类型HASH分区)
- [2.4 创建SYMBOL类型HASH分区](#2.4 创建SYMBOL类型HASH分区)
- 三、HASH分区查询
-
- [3.1 查询特点](#3.1 查询特点)
- [3.2 查询优化](#3.2 查询优化)
- 四、COMPO组合分区
-
- [4.1 什么是COMPO分区](#4.1 什么是COMPO分区)
- [4.2 COMPO分区优势](#4.2 COMPO分区优势)
- [4.3 创建COMPO分区](#4.3 创建COMPO分区)
- [4.4 RANGE + HASH组合](#4.4 RANGE + HASH组合)
- [4.5 VALUE + RANGE组合](#4.5 VALUE + RANGE组合)
- 五、COMPO分区查询优化
-
- [5.1 多维度分区裁剪](#5.1 多维度分区裁剪)
- [5.2 查询性能对比](#5.2 查询性能对比)
- 六、分区策略选择
-
- [6.1 选择决策树](#6.1 选择决策树)
- [6.2 策略对比](#6.2 策略对比)
- [6.3 最佳实践](#6.3 最佳实践)
- 七、实战案例
-
- [7.1 工业物联网数据分区](#7.1 工业物联网数据分区)
- [7.2 多租户SaaS数据分区](#7.2 多租户SaaS数据分区)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB HASH分区和COMPO组合分区策略。从HASH分区的均匀分布原理到COMPO分区的多维度设计,从分区创建到查询优化,全面介绍这两种分区策略的应用场景和最佳实践。通过丰富的代码示例,帮助读者掌握复杂场景下的分区设计技能。
一、HASH分区概述
1.1 什么是HASH分区
HASH分区通过对分区列的值进行哈希运算,将数据均匀分布到指定数量的分区中:
HASH分区原理
原始数据
哈希运算
分区1
分区2
分区3
分区4
数据均匀分布
1.2 HASH分区特点
| 特点 | 说明 |
|---|---|
| 均匀分布 | 数据自动均匀分布 |
| 分区固定 | 分区数量预先确定 |
| 适合高基数 | 适合值域很大的列 |
| 查询需扫描 | 精确查询需扫描所有分区 |
1.3 适用场景
| 场景 | 说明 |
|---|---|
| 高基数列 | 设备ID、用户ID等 |
| 均匀分布 | 需要数据均匀分布 |
| 写入优化 | 并行写入优化 |
| 组合分区 | 作为组合分区的子分区 |
二、创建HASH分区
2.1 基本语法
python
// HASH分区语法
db = database("dfs://db_name", HASH, [data_type, bucket_count])
// 参数说明:
// - data_type: 分区列的数据类型
// - bucket_count: 哈希桶数量(分区数)
2.2 创建INT类型HASH分区
python
// 按设备ID哈希分区(10个分区)
db = database("dfs://hash_db", HASH, [INT, 10])
// 创建分区表
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `device_id)
// 插入数据
t = table(
take(1..1000, 100000) as device_id,
take(now(), 100000) as timestamp,
rand(20.0..30.0, 100000) as temperature,
rand(40.0..60.0, 100000) as humidity
)
loadTable("dfs://hash_db", "sensor_data").append!(t)
// 查看各分区数据量
select count(*) from t group by device_id % 10 as partition
2.3 创建STRING类型HASH分区
python
// 按用户ID哈希分区
db = database("dfs://user_hash_db", HASH, [STRING, 20])
// 创建分区表
schema = table(1:0,
`user_id`timestamp`action`value,
[STRING, TIMESTAMP, SYMBOL, DOUBLE])
db.createPartitionedTable(schema, `user_action, `user_id)
2.4 创建SYMBOL类型HASH分区
python
// 按设备名称哈希分区
db = database("dfs://symbol_hash_db", HASH, [SYMBOL, 50])
// 创建分区表
schema = table(1:0,
`device_name`timestamp`status`value,
[SYMBOL, TIMESTAMP, SYMBOL, DOUBLE])
db.createPartitionedTable(schema, `device_status, `device_name)
三、HASH分区查询
3.1 查询特点
python
// HASH分区查询需要扫描所有分区
t = loadTable("dfs://hash_db", "sensor_data")
// 精确查询(扫描所有分区)
select * from t where device_id = 100
// 范围查询(扫描所有分区)
select * from t where device_id between 1 and 100
// 聚合查询
select count(*) from t
3.2 查询优化
python
// HASH分区适合全量扫描场景
// 不适合精确查询场景
// 优化方案:使用组合分区
// 时间RANGE + 设备HASH
db = database("dfs://combo_hash_db", COMPO,
[RANGE, 2024.01.01..2024.12.31,
HASH, [INT, 10]])
// 这样可以按时间裁剪分区
select * from loadTable("dfs://combo_hash_db", "sensor_data")
where date(timestamp) = 2024.01.15 and device_id = 100
四、COMPO组合分区
4.1 什么是COMPO分区
COMPO分区是多种分区策略的组合,支持多维度分区:
COMPO组合分区
原始数据
第一层: 时间RANGE
第二层: 设备VALUE
分区1: 2024.01.01 + 设备1-10
分区2: 2024.01.01 + 设备11-20
分区3: 2024.01.02 + 设备1-10
分区4: 2024.01.02 + 设备11-20
4.2 COMPO分区优势
| 优势 | 说明 |
|---|---|
| 多维度 | 支持多列分区 |
| 灵活查询 | 支持多维度裁剪 |
| 均衡分布 | 数据分布更均匀 |
| 精细管理 | 分区管理更精细 |
4.3 创建COMPO分区
python
// 时间RANGE + 设备VALUE组合分区
db = database("dfs://compo_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)
// 插入数据
t = table(
take(1..100, 100000) as device_id,
take(2024.01.01T00:00:00 + 0..99999 * 600, 100000) as timestamp,
rand(20.0..30.0, 100000) as temperature,
rand(40.0..60.0, 100000) as humidity
)
loadTable("dfs://compo_db", "sensor_data").append!(t)
4.4 RANGE + HASH组合
python
// 时间RANGE + 设备HASH组合分区
db = database("dfs://compo_hash_db", COMPO,
[RANGE, 2024.01.01..2024.12.31, // 第一层:时间范围
HASH, [INT, 10]]) // 第二层:设备哈希
// 创建分区表
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `timestamp`device_id)
4.5 VALUE + RANGE组合
python
// 设备VALUE + 时间RANGE组合分区
db = database("dfs://compo_vr_db", COMPO,
[VALUE, 1..100, // 第一层:设备值
RANGE, 2024.01.01..2024.12.31]) // 第二层:时间范围
// 创建分区表
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `device_id`timestamp)
五、COMPO分区查询优化
5.1 多维度分区裁剪
python
// COMPO分区支持多维度裁剪
t = loadTable("dfs://compo_db", "sensor_data")
// 按时间裁剪(第一层)
select count(*) from t where date(timestamp) = 2024.01.15
// 按设备裁剪(第二层)
select count(*) from t where device_id = 50
// 双维度裁剪(最优)
select count(*) from t
where date(timestamp) = 2024.01.15 and device_id = 50
// 查看执行计划
explain select * from t
where date(timestamp) = 2024.01.15 and device_id = 50
5.2 查询性能对比
python
// 性能对比测试
def testQueryPerformance() {
t = loadTable("dfs://compo_db", "sensor_data")
// 测试1:全表扫描
timer {
select count(*) from t
}
// 测试2:时间过滤
timer {
select count(*) from t where date(timestamp) = 2024.01.15
}
// 测试3:设备过滤
timer {
select count(*) from t where device_id = 50
}
// 测试4:双维度过滤
timer {
select count(*) from t
where date(timestamp) = 2024.01.15 and device_id = 50
}
}
testQueryPerformance()
六、分区策略选择
6.1 选择决策树
按时间范围
按枚举值
均匀分布
多维度
大
小
时间
设备
选择分区策略
查询模式
RANGE分区
VALUE分区
HASH分区
COMPO分区
数据量
时间+其他组合
纯时间分区
第一层
RANGE + HASH/VALUE
VALUE + RANGE
6.2 策略对比
| 策略 | 适用场景 | 查询优势 | 写入优势 |
|---|---|---|---|
| VALUE | 离散值、低基数 | 精确匹配快 | 按值分布 |
| RANGE | 连续值、时间 | 范围查询快 | 按时间写入 |
| HASH | 高基数、均匀 | 全量扫描 | 并行写入 |
| COMPO | 多维度 | 多维度裁剪 | 灵活分布 |
6.3 最佳实践
| 场景 | 推荐策略 | 说明 |
|---|---|---|
| 物联网数据 | RANGE + HASH | 时间+设备 |
| 日志数据 | RANGE + VALUE | 时间+类型 |
| 交易数据 | RANGE + HASH | 时间+用户 |
| 监控数据 | VALUE + RANGE | 设备+时间 |
七、实战案例
7.1 工业物联网数据分区
python
// 工业物联网数据:时间RANGE + 设备HASH
db = database("dfs://iot_compo", COMPO,
[RANGE, 2024.01.01..2024.12.31, // 按日分区
HASH, [INT, 100]]) // 设备哈希100个桶
// 创建设备数据表
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`device_id)
// 创建告警表
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`device_id)
// 模拟数据
def simulateIoTData(days, devices) {
for (d in 0..(days-1)) {
date = 2024.01.01 + d
data = table(
take(1..devices, devices * 100) as device_id,
take(dateT00:00:00 + 0..(devices*100-1) * 864, devices * 100) as timestamp,
rand(20.0..30.0, devices * 100) as temperature,
rand(40.0..60.0, devices * 100) as humidity,
rand(1000.0..1020.0, devices * 100) as pressure,
rand(0.0..5.0, devices * 100) as vibration,
rand(100.0..500.0, devices * 100) as power
)
loadTable("dfs://iot_compo", "device_data").append!(data)
}
}
simulateIoTData(30, 1000) // 30天,1000设备
// 查询某日某设备数据
select * from loadTable("dfs://iot_compo", "device_data")
where date(timestamp) = 2024.01.15 and device_id = 500
limit 10
7.2 多租户SaaS数据分区
python
// 多租户数据:租户VALUE + 时间RANGE
tenants = `tenant_001`tenant_002`tenant_003`tenant_004`tenant_005
db = database("dfs://saas_compo", COMPO,
[VALUE, tenants, // 租户分区
RANGE, 2024.01.01..2024.12.31]) // 时间分区
// 创建订单表
schema = table(1:0,
`tenant_id`order_id`timestamp`user_id`amount`status,
[SYMBOL, STRING, TIMESTAMP, STRING, DOUBLE, SYMBOL])
db.createPartitionedTable(schema, `orders, `tenant_id`timestamp)
// 查询某租户某日订单
select * from loadTable("dfs://saas_compo", "orders")
where tenant_id = `tenant_001`
and date(timestamp) = 2024.01.15
八、总结
本文详细介绍了DolphinDB HASH分区和COMPO组合分区:
- HASH分区:均匀分布、高基数、写入优化
- COMPO分区:多维度、灵活查询、精细管理
- 组合策略:RANGE+HASH、RANGE+VALUE、VALUE+RANGE
- 查询优化:多维度分区裁剪
- 策略选择:根据查询模式和业务场景选择
思考题:
- HASH分区和VALUE分区有什么区别?
- 什么时候应该使用COMPO组合分区?
- 如何设计物联网数据的分区策略?