目录
-
- 摘要
- 一、数据压缩概述
-
- [1.1 为什么需要数据压缩](#1.1 为什么需要数据压缩)
- [1.2 DolphinDB压缩特点](#1.2 DolphinDB压缩特点)
- [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 排序列优化](#4.3 排序列优化)
- 五、冷热数据分离
-
- [5.1 分层存储](#5.1 分层存储)
- [5.2 数据迁移](#5.2 数据迁移)
- [5.3 降采样存储](#5.3 降采样存储)
- 六、存储监控
-
- [6.1 存储空间监控](#6.1 存储空间监控)
- [6.2 压缩率监控](#6.2 压缩率监控)
- 七、最佳实践
-
- [7.1 压缩策略](#7.1 压缩策略)
- [7.2 存储优化清单](#7.2 存储优化清单)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB数据压缩与存储优化技术。从压缩算法原理到配置方法,从存储策略设计到空间优化,从性能测试到最佳实践,全面介绍如何降低存储成本、提升查询性能。通过丰富的代码示例,帮助读者掌握数据压缩和存储优化的核心技能。
一、数据压缩概述
1.1 为什么需要数据压缩
工业物联网数据量巨大,存储成本高昂:
数据压缩价值
原始数据
100TB
压缩后
10TB
存储成本降低90%
查询性能提升
网络传输减少
1.2 DolphinDB压缩特点
| 特点 | 说明 |
|---|---|
| 列式压缩 | 按列存储,压缩率高 |
| 时序压缩 | 针对时序数据优化 |
| 自动压缩 | 自动选择压缩算法 |
| 透明解压 | 查询时自动解压 |
1.3 压缩算法对比
| 算法 | 压缩比 | 压缩速度 | 解压速度 | 适用场景 |
|---|---|---|---|---|
| LZ4 | 中 | 快 | 快 | 通用场景 |
| ZSTD | 高 | 中 | 中 | 高压缩比 |
| DELTA | 高 | 快 | 快 | 渐变数据 |
| BITMAP | 高 | 快 | 快 | 低基数列 |
二、压缩配置
2.1 数据库级压缩
python
// 创建数据库时指定压缩
db = database("dfs://compressed_db", VALUE, 1..100)
// 创建表时指定压缩
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(
schema,
`sensor_data,
`device_id,
, // sortColumns
true, // enableCompression
"ZSTD" // compressionAlgorithm
)
2.2 列级压缩
python
// 不同列使用不同压缩算法
schema = table(1:0,
`device_id`timestamp`temperature`humidity`status,
[INT, TIMESTAMP, DOUBLE, DOUBLE, SYMBOL])
// 创建表时配置列压缩
db.createPartitionedTable(
schema,
`sensor_data,
`device_id,
,
true,
["LZ4", "DELTA", "ZSTD", "ZSTD", "BITMAP"] // 各列压缩算法
)
2.3 压缩算法选择
python
// 根据数据特点选择压缩算法
// 整数列:DELTA(渐变数据)
// device_id: DELTA(连续整数)
// 时间列:DELTA(时间递增)
// timestamp: DELTA
// 浮点数列:ZSTD(随机数据)
// temperature: ZSTD
// 符号列:BITMAP(低基数)
// status: BITMAP
三、压缩效果测试
3.1 测试数据准备
python
// 创建测试数据
def generateTestData(rows) {
return table(
take(1..100, rows) as device_id,
2024.01.01T00:00:00 + 0..(rows-1) * 1000 as timestamp,
rand(20.0..30.0, rows) as temperature,
rand(40.0..60.0, rows) as humidity,
take(`online`offline`error, rows) as status
)
}
data = generateTestData(10000000) // 1000万行
3.2 压缩效果对比
python
// 测试不同压缩算法
// 1. 无压缩
db1 = database("dfs://no_compress", VALUE, 1..100)
db1.createPartitionedTable(schema, `data1, `device_id, , false)
loadTable("dfs://no_compress", "data1").append!(data)
// 2. LZ4压缩
db2 = database("dfs://lz4_compress", VALUE, 1..100)
db2.createPartitionedTable(schema, `data2, `device_id, , true, "LZ4")
loadTable("dfs://lz4_compress", "data2").append!(data)
// 3. ZSTD压缩
db3 = database("dfs://zstd_compress", VALUE, 1..100)
db3.createPartitionedTable(schema, `data3, `device_id, , true, "ZSTD")
loadTable("dfs://zstd_compress", "data3").append!(data)
// 4. 列级压缩
db4 = database("dfs://col_compress", VALUE, 1..100)
db4.createPartitionedTable(schema, `data4, `device_id, , true,
["DELTA", "DELTA", "ZSTD", "ZSTD", "BITMAP"])
loadTable("dfs://col_compress", "data4").append!(data)
3.3 查看压缩效果
python
// 查看各表存储大小
def getTableSize(dbPath, tableName) {
meta = getTabletsMeta(dbPath, tableName)
return sum(meta.size)
}
sizes = table(
["无压缩", "LZ4", "ZSTD", "列级压缩"] as name,
[
getTableSize("dfs://no_compress", "data1"),
getTableSize("dfs://lz4_compress", "data2"),
getTableSize("dfs://zstd_compress", "data3"),
getTableSize("dfs://col_compress", "data4")
] as size_bytes
)
// 计算压缩比
select name, size_bytes,
size_bytes / sizes[0].size_bytes as compression_ratio
from sizes
四、存储优化策略
4.1 数据类型优化
python
// 选择合适的数据类型
// 不推荐
t1 = table(
1..100 as id,
"device_" + string(1..100) as name, // STRING
25.5 as temperature // DOUBLE
)
// 推荐
t2 = table(
1..100 as id,
symbol("device_" + string(1..100)) as name, // SYMBOL(更省空间)
25.5f as temperature // FLOAT(精度够用)
)
// 数据类型大小对比
// INT: 4字节
// LONG: 8字节
// FLOAT: 4字节
// DOUBLE: 8字节
// SYMBOL: 4字节(引用)
// STRING: 变长
4.2 分区优化
python
// 合理的分区大小
// 不推荐:分区过小
db1 = database("dfs://small_partition", VALUE, 1..10000) // 10000个分区
// 不推荐:分区过大
db2 = database("dfs://large_partition", RANGE, [2024.01.01, 2025.01.01]) // 1个分区
// 推荐:分区大小1-10GB
db3 = database("dfs://optimal_partition", COMPO,
[RANGE, 2024.01.01..2024.12.31, // 按日分区
HASH, [INT, 10]]) // 哈希分桶
4.3 排序列优化
python
// 设置排序列加速查询
db = database("dfs://sorted_db", VALUE, 1..100)
schema = table(1:0,
`device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE])
// 创建表时指定排序列
db.createPartitionedTable(
schema,
`sensor_data,
`device_id,
`timestamp // 按时间排序
)
// 排序后查询更快
select * from loadTable("dfs://sorted_db", "sensor_data")
where device_id = 1 and timestamp between 2024.01.01 and 2024.01.02
五、冷热数据分离
5.1 分层存储
数据分层
热数据
最近7天
SSD存储
温数据
7天-3月
HDD存储
冷数据
3月以上
对象存储
5.2 数据迁移
python
// 数据迁移函数
def migrateToCold(dbPath, tableName, cutoffDate) {
db = database(dbPath)
t = loadTable(db, tableName)
// 查询冷数据
coldData = select * from t
where date(timestamp) < cutoffDate
// 写入冷存储
cold_db = database("dfs://cold_storage")
loadTable(cold_db, tableName).append!(coldData)
// 删除原数据
dates = distinct(date(coldData.timestamp))
for (d in dates) {
dropPartition(db, [d])
}
return coldData.rows()
}
// 定期迁移
scheduleJob("migrate_cold", "冷数据迁移",
def() { migrateToCold("dfs://iot_db", "sensor_data", today() - 90) },
02:00, 2024.01.01, 2030.12.31, 'D')
5.3 降采样存储
python
// 历史数据降采样
def downsampleData(dbPath, tableName, startDate) {
t = loadTable(dbPath, tableName)
// 降采样:1分钟→1小时
downsampled = select device_id,
bar(timestamp, 1h) as hour,
avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as count
from t
where date(timestamp) = startDate
group by device_id, bar(timestamp, 1h)
// 写入降采样表
loadTable(dbPath, "sensor_data_hourly").append!(downsampled)
return downsampled.rows()
}
// 每日降采样
scheduleJob("downsample", "数据降采样",
def() { downsampleData("dfs://iot_db", "sensor_data", today() - 1) },
01:00, 2024.01.01, 2030.12.31, 'D')
六、存储监控
6.1 存储空间监控
python
// 查看数据库大小
def getDatabaseSize(dbPath) {
tables = tables(dbPath)
total = 0
for (t in tables) {
total += getTableSize(dbPath, t.name)
}
return total
}
// 查看各表大小
def listTableSizes(dbPath) {
tables = tables(dbPath)
return select name, getTableSize(dbPath, name) as size_bytes
from tables
order by size_bytes desc
}
listTableSizes("dfs://iot_db")
6.2 压缩率监控
python
// 监控压缩效果
def monitorCompression(dbPath, tableName) {
meta = getTabletsMeta(dbPath, tableName)
return select partition,
count(*) as chunk_count,
sum(size) as compressed_size,
sum(originalSize) as original_size,
sum(originalSize) / sum(size) as compression_ratio
from meta
group by partition
}
monitorCompression("dfs://iot_db", "sensor_data")
七、最佳实践
7.1 压缩策略
| 数据类型 | 推荐算法 | 说明 |
|---|---|---|
| 时间列 | DELTA | 时间递增 |
| 整数列 | DELTA | 连续整数 |
| 浮点列 | ZSTD | 随机数据 |
| 符号列 | BITMAP | 低基数 |
| 字符串 | LZ4 | 通用场景 |
7.2 存储优化清单
| 优化项 | 建议 |
|---|---|
| 数据类型 | 使用SYMBOL替代STRING |
| 分区大小 | 1-10GB |
| 排序列 | 常用查询列 |
| 压缩算法 | 根据数据特点选择 |
| 冷热分离 | 定期迁移历史数据 |
| 降采样 | 历史数据降精度 |
八、总结
本文详细介绍了DolphinDB数据压缩与存储优化:
- 压缩算法:LZ4、ZSTD、DELTA、BITMAP
- 压缩配置:数据库级、列级压缩
- 压缩测试:效果对比、性能测试
- 存储优化:数据类型、分区、排序
- 冷热分离:分层存储、数据迁移、降采样
- 存储监控:空间监控、压缩率监控
思考题:
- 如何选择合适的压缩算法?
- 如何设计冷热数据分离策略?
- 如何监控存储空间使用情况?