三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

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

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


一、前置思考

1.1 存储选型决定应用的天花板

很多鸿蒙应用上线后才暴露存储问题:启动慢是因为 Preferences 被塞进了几 MB 数据、列表卡顿是因为把关系型数据硬塞进 KV、跨设备功能加不上是因为当初没选分布式存储。存储选型一旦定错,重构成本远高于其他任何模块。

HarmonyOS 提供四大存储体系,各有所长:

存储体系代表 API本质适合
Preferences@kit.ArkDatapreferencesXML/键值对轻量配置、开关、用户偏好
KV StoredistributedKVStore键值对 + 可同步高频读写、Token/缓存、跨设备同步
RelationalStorerelationalStoreSQLite 关系型结构化、关联查询、事务
分布式存储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 =====asyncfunctionusePreferences(context:common.Context):Promise<void>{conststore=awaitpreferences.getPreferences(context,'my_prefs');awaitstore.put('theme','dark');awaitstore.flush();// 关键: 只有 flush 才落盘consttheme=awaitstore.get('theme','light');}// ===== KV Store (单机) =====asyncfunctionuseKV(context:common.Context):Promise<void>{constkvManager=distributedKVStore.createKVManager({bundleName:'com.example.app',context:context});constkvStore=awaitkvManager.getKVStore('my_kv',{createIfMissing:true,securityLevel:distributedKVStore.SecurityLevel.S1});awaitkvStore.put('token','abc123');consttoken=awaitkvStore.get('token');}// ===== RelationalStore =====asyncfunctionuseRdb(context:common.Context):Promise<void>{constconfig:relationalStore.StoreConfig={name:'user.db',securityLevel:relationalStore.SecurityLevel.S1};constrdb=awaitrelationalStore.getRdbStore(context,config);awaitrdb.executeSql('CREATE TABLE IF NOT EXISTS user(id INTEGER PRIMARY KEY, name TEXT)');awaitrdb.insert('user',{id:1,name:'张三'}asrelationalStore.ValuesBucket);}

3.2 写入模式对比(关键差异)

维度PreferencesKV StoreRelationalStore
写入落盘flush 全量序列化WAL 顺序写WAL + 页刷新
单条写入延迟~1-3ms(小数据)~0.2-1ms~0.5-2ms
批量写入差(全量重写)优(顺序 WAL)优(事务)
读取路径内存缓存mmap 直读B-Tree 查询
大数据量差(全量加载)

四、企业级实战落地

4.1 性能基准测试框架(Benchmark)

interfaceBenchResult{op:string;// 操作名count:number;// 次数totalMs:number;// 总耗时avgMs:number;// 平均单次qps:number;// 每秒次数}asyncfunctionbenchWrite(put:(i:number)=>Promise<void>,count:number):Promise<BenchResult>{constt0=Date.now();for(leti=0;i<count;i++){awaitput(i);}consttotal=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
Preferences15800ms210ms1.58ms633
KV Store2600ms150ms0.26ms3846
RelationalStore7200ms680ms0.72ms1389
分布式KV(本地)2800ms180ms0.28ms3571

结论:写场景 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 StoreasyncfunctionmigrateIfLarge(pref:preferences.Preferences,kv:distributedKVStore.SingleKVStore):Promise<void>{constall=awaitpref.getAll();if(Object.keys(all).length>500){for(constkofObject.keys(all)){awaitkv.put(k,JSON.stringify(all[k]));}// 迁移后清理 Preferencesfor(constkofObject.keys(all)){awaitpref.delete(k);}awaitpref.flush();}}

5.2 混合读写负载优化

读多写少 (配置/商品详情) → KV Store + 内存缓存 写多读少 (日志/埋点) → KV Store NO_LOG 模式 + 批量 flush 事务强一致 (订单/支付) → RelationalStore 事务 高并发读写 (会话/计数器) → KV Store + 合并写入

六、高阶总结与最佳实践

  1. 选型先行:存储方案在架构设计阶段定,上线后再换代价巨大。
  2. 各司其职:Preferences 存配置、KV 存键值高频数据、RDB 存结构化业务数据、分布式存跨端数据。
  3. 混合架构:企业级应用几乎都是"内存缓存 + KV + RDB + 分布式"的组合。
  4. 基准说话:用统一 Benchmark 框架对比性能,数据驱动选型而非直觉。
  5. 持续演进:存储选型不是一次性的,数据量增长后要主动评估迁移(如 Preferences → KV)。

一句话记住:配置用 Preferences,键值高频用 KV,结构化查询用 RDB,跨设备同步用分布式——选型先于实现,基准先于直觉。

← 返回列表