add仅插入新记录,主键冲突报constrainterror;put为插入或更新,主键存在则覆盖、不存在则新增;批量写入应优先用put+transaction,分块处理并预处理数据结构。

add 和 put 的核心区别必须清楚
add 只能插入新记录,如果主键已存在,直接报错(ConstraintError);put 是“插入或更新”,无论主键是否存在都成功写入,已存在则覆盖,不存在则新增。对海量结构化数据批量写入场景,除非业务强制要求拒绝重复,否则优先用 put——它避免了先查后插的额外开销,也省去错误捕获和重试逻辑。
批量写入必须用 transaction + objectStore.add/put,别单条循环
每调用一次 add/put 都触发一次数据库 I/O,单条执行在万级数据下会极慢且易超时。正确做法是:在一个 readwrite 事务 中,连续调用多次 add 或 put:
- 事务生命周期内所有操作共享同一底层连接,I/O 合并,性能提升数倍至数十倍
- 确保所有操作在
transaction.oncomplete或await transaction.done后再认为写入完成 - 避免在循环中新建事务(比如 for 每次 newTransaction),那等于退化成单条模式
示例片段:
const tx = db.transaction('users', 'readwrite');
const store = tx.objectStore('users');
dataList.forEach(item => store.put(item)); // 推荐:统一用 put
tx.oncomplete = () => console.log('全部写入完成');
tx.onerror = e => console.error('写入失败', e.target.error);
写入前预处理结构,减少运行时开销
IndexedDB 不解析对象嵌套、不自动类型转换、不校验 schema。若原始数据字段冗余、含函数、undefined 或深层嵌套(如 item.meta.config.settings.xxx),不仅序列化变慢,还可能因不可序列化值(如 Date 对象未转字符串)导致静默失败或截断。建议:
- 用
JSON.parse(JSON.stringify(obj))快速深克隆并剥离不可存值(注意:会丢掉 Date、RegExp、undefined、function) - 对时间字段统一转为 ISO 字符串(
new Date().toISOString())或时间戳(number) - 提前剔除空字段或无意义嵌套,扁平化常用查询字段(如把
address.city提到根级city: 'Beijing')
大体积数据分块 + 错误隔离,防事务撑爆或中断全盘失败
单个事务写入超过几万条或总数据量 >10MB,容易触发浏览器内存限制或事务超时(尤其在低端设备)。稳妥策略是分块(chunk)提交:
- 每块 500–2000 条(根据单条平均大小动态调整),块间用
await transaction.done确保落盘再启下一块 - 每块独立事务,某块失败不影响其余;可记录失败块索引,支持断点续传
- 配合
indexedDB.cmp()做主键范围校验(如确认待写入 ID 是否全大于当前最大 ID),避免逻辑冲突
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











