鸿蒙四大存储体系高级深度对比:Preferences/RDB KV/关系型数据库/分布式存储选型架构与性能基准测试
·


一、前置思考
1.1 存储选型决定应用的天花板
很多鸿蒙应用上线后才暴露存储问题:启动慢是因为 Preferences 被塞进了几 MB 数据、列表卡顿是因为把关系型数据硬塞进 KV、跨设备功能加不上是因为当初没选分布式存储。存储选型一旦定错,重构成本远高于其他任何模块。
HarmonyOS 提供四大存储体系,各有所长:
| 存储体系 | 代表 API | 本质 | 适合 |
|---|---|---|---|
| Preferences | @kit.ArkData preferences |
XML/键值对 | 轻量配置、开关、用户偏好 |
| KV Store | distributedKVStore | 键值对 + 可同步 | 高频读写、Token/缓存、跨设备同步 |
| RelationalStore | relationalStore | SQLite 关系型 | 结构化、关联查询、事务 |
| 分布式存储 | distributedData 全家桶 | 上述能力的分布式化 | 多设备数据协同 |
1.2 选型错误的典型代价
❌ 错误选型1: 把 2MB 的用户行为日志写入 Preferences
→ 每次启动全量加载, 启动耗时 +800ms, 掉帧明显
❌ 错误选型2: 聊天记录用 KV Store 存
→ 无法按会话/时间/发送者组合查询, 只能全量拉取过滤
❌ 错误选型3: 商品列表用 RelationalStore 高频写入
→ 每次写入走完整 SQL 解析 + 事务, 写入吞吐只有 KV 的 1/5
❌ 错误选型4: 多设备同步需求却选单机存储
→ 跨设备功能无法实现, 只能自己造轮子同步
1.3 本文价值
本文给出四大存储体系的底层机制对比、性能基准测试方法、选型决策树,让你在架构设计阶段就做对选择。
二、核心原理
2.1 四大存储体系架构全景
┌─────────────────────────────────────────────────────┐
│ 应用层 (ArkTS / NAPI) │
├─────────────────────────────────────────────────────┤
│ Preferences KV Store RelationalStore │
│ (XML键值) (键值+同步) (SQLite关系型) │
├─────────────────────────────────────────────────────┤
│ Distributed Data 分布式层 │
│ 分布式KV / 分布式数据库 / 分布式数据对象 │
├─────────────────────────────────────────────────────┤
│ 底层存储引擎 (mmap / WAL / B-Tree) │
└─────────────────────────────────────────────────────┘
2.2 Preferences 底层机制
- 基于 XML 文件,整个文件一次性加载进内存,
get走内存索引; - 每次
put触发全文件序列化回写(除非批量 flush),大数据量下写入极慢; - 进程内加缓存 + 锁,跨进程/跨设备不可见。
结论:Preferences 是"配置档"不是"数据库",数据量应控制在 KB 级。
2.3 KV Store 底层机制
- 单机模式基于 mmap 内存映射 + Hash 索引 + WAL 预写日志(详见第78篇);
- 写入先落 WAL(顺序 IO)再刷内存,读走 mmap,读写性能远超 Preferences;
- 支持
NO_LOG/LOG_ONLY/LOG_AND_FLUSH三种写入模式; - 分布式模式下支持 CRDT 多版本合并、跨设备同步。
2.4 RelationalStore 底层机制
- 基于 SQLite 引擎,B-Tree 索引、事务、SQL 查询优化器(详见第77篇);
- 数据按行存储,支持复杂关联查询(JOIN/GROUP BY/子查询);
- 事务隔离 + WAL 模式保证一致性;
- 性能瓶颈:SQL 解析、索引维护、锁竞争——高频写入场景不占优。
2.5 分布式存储
- 分布式 KV:多端 CRDT 同步;
- 分布式数据对象:多端内存共享同一对象;
- 分布式数据库:跨设备 RDB 同步(受限支持);
- 依赖软总线组网、设备认证,弱网下有同步延迟。
三、源码/API 深度解析
3.1 四大存储的 ArkTS 使用范式
import { preferences } from '@kit.ArkData';
import { distributedKVStore } from '@kit.ArkData';
import { relationalStore } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';
// ===== Preferences =====
async function usePreferences(context: common.Context): Promise<void> {
const store = await preferences.getPreferences(context, 'my_prefs');
await store.put('theme', 'dark');
await store.flush(); // 关键: 只有 flush 才落盘
const theme = await store.get('theme', 'light');
}
// ===== KV Store (单机) =====
async function useKV(context: common.Context): Promise<void> {
const kvManager = distributedKVStore.createKVManager({
bundleName: 'com.example.app',
context: context
});
const kvStore = await kvManager.getKVStore('my_kv',
{ createIfMissing: true, securityLevel: distributedKVStore.SecurityLevel.S1 });
await kvStore.put('token', 'abc123');
const token = await kvStore.get('token');
}
// ===== RelationalStore =====
async function useRdb(context: common.Context): Promise<void> {
const config: relationalStore.StoreConfig = {
name: 'user.db',
securityLevel: relationalStore.SecurityLevel.S1
};
const rdb = await relationalStore.getRdbStore(context, config);
await rdb.executeSql('CREATE TABLE IF NOT EXISTS user(id INTEGER PRIMARY KEY, name TEXT)');
await rdb.insert('user', { id: 1, name: '张三' } as relationalStore.ValuesBucket);
}
3.2 写入模式对比(关键差异)
| 维度 | Preferences | KV Store | RelationalStore |
|---|---|---|---|
| 写入落盘 | flush 全量序列化 | WAL 顺序写 | WAL + 页刷新 |
| 单条写入延迟 | ~1-3ms(小数据) | ~0.2-1ms | ~0.5-2ms |
| 批量写入 | 差(全量重写) | 优(顺序 WAL) | 优(事务) |
| 读取路径 | 内存缓存 | mmap 直读 | B-Tree 查询 |
| 大数据量 | 差(全量加载) | 优 | 优 |
四、企业级实战落地
4.1 性能基准测试框架(Benchmark)
interface BenchResult {
op: string; // 操作名
count: number; // 次数
totalMs: number; // 总耗时
avgMs: number; // 平均单次
qps: number; // 每秒次数
}
async function benchWrite(put: (i: number) => Promise<void>, count: number): Promise<BenchResult> {
const t0 = Date.now();
for (let i = 0; i < count; i++) { await put(i); }
const total = Date.now() - t0;
return {
op: 'write', count: count, totalMs: total,
avgMs: total / count, qps: Math.round(count / (total / 1000))
};
}
测试方案:
- 预热 100 次后开始计时(消除引擎初始化影响);
- 小数据量(100 条)与大数据量(1 万条)分别测;
- 读/写/混合 三组数据,记录平均延迟与 QPS。
4.2 基准测试实测数据(模拟)
| 存储 | 写入 1 万条 | 读取 1 万条 | 单条写入均值 | QPS |
|---|---|---|---|---|
| Preferences | 15800ms | 210ms | 1.58ms | 633 |
| KV Store | 2600ms | 150ms | 0.26ms | 3846 |
| RelationalStore | 7200ms | 680ms | 0.72ms | 1389 |
| 分布式KV(本地) | 2800ms | 180ms | 0.28ms | 3571 |
结论:写场景 KV 最快,读小数据 Preferences 有缓存优势,关系型查询能力最强但吞吐不是长项。
4.3 选型决策树
数据是否需要跨设备同步?
├─ 是 → 分布式KV / 分布式数据对象
│ └─ 数据是结构化且需关联查询? → 分布式数据库(受限)或本地RDB+同步层
└─ 否 → 数据结构化程度?
├─ 高(需要JOIN/事务/索引) → RelationalStore
├─ 中(纯键值+高频读写) → KV Store
└─ 低(少量配置/偏好) → Preferences
4.4 多存储混合架构(企业实践)
大型应用不会只用一种存储,而是分层混合:
UI 状态缓存 → 内存缓存(LruCache)
用户偏好/设置 → Preferences
登录Token/会话 → KV Store (加密)
业务主数据(订单/商品) → RelationalStore
跨设备同步的数据 → 分布式KV Store
大文件(图片/视频) → 文件系统 + 数据库存元数据
五、问题排查与性能优化
| 问题 | 原因 | 优化 |
|---|---|---|
| 启动慢 | Preferences 塞入大数据 | 数据迁移到 KV/RDB |
| 写入卡顿 | Preferences 频繁 flush | 批量改一次 flush |
| 查询慢 | RDB 无索引 | 加索引(详见第77篇) |
| 高频读写慢 | 没用 KV | 换 KV Store |
| 跨设备不同步 | 用了单机存储 | 换分布式存储 |
| 数据量膨胀 | 缓存当永久数据 | 区分 cache 与 files |
5.1 Preferences 大数据迁移
// 检测到 Preferences 数据超过阈值 → 迁移到 KV Store
async function migrateIfLarge(pref: preferences.Preferences,
kv: distributedKVStore.SingleKVStore): Promise<void> {
const all = await pref.getAll();
if (Object.keys(all).length > 500) {
for (const k of Object.keys(all)) { await kv.put(k, JSON.stringify(all[k])); }
// 迁移后清理 Preferences
for (const k of Object.keys(all)) { await pref.delete(k); }
await pref.flush();
}
}
5.2 混合读写负载优化
读多写少 (配置/商品详情) → KV Store + 内存缓存
写多读少 (日志/埋点) → KV Store NO_LOG 模式 + 批量 flush
事务强一致 (订单/支付) → RelationalStore 事务
高并发读写 (会话/计数器) → KV Store + 合并写入
六、高阶总结与最佳实践
- 选型先行:存储方案在架构设计阶段定,上线后再换代价巨大。
- 各司其职:Preferences 存配置、KV 存键值高频数据、RDB 存结构化业务数据、分布式存跨端数据。
- 混合架构:企业级应用几乎都是"内存缓存 + KV + RDB + 分布式"的组合。
- 基准说话:用统一 Benchmark 框架对比性能,数据驱动选型而非直觉。
- 持续演进:存储选型不是一次性的,数据量增长后要主动评估迁移(如 Preferences → KV)。
一句话记住:配置用 Preferences,键值高频用 KV,结构化查询用 RDB,跨设备同步用分布式——选型先于实现,基准先于直觉。
更多推荐




所有评论(0)