请问,IndexedDB在定义了唯一索引和普通索引之后,在仓库的结构上会有什么变化吗?

请问IndexedDB在定义了唯一索引和普通索引之后,在仓库的结构上会有什么变化吗?

我亲测好像没有任何变化:

    request.onupgradeneeded = function (e) {
      db = e.target.result;

      // 创建存储库
      var objectStore = db.createObjectStore('students', {
        keyPath: 'uuid',  // 这是主键
        autoIncrement: true  // 实现自增
      });

      // 创建索引   在后面查询数据的时间可以依据索引来查询
      // 基于自己需要进行创建
      objectStore.createIndex('uuid','uuid', {
        unique: true
      });
      objectStore.createIndex('name', 'name', {
        unique: false
      });
      objectStore.createIndex('age', 'age', {
        unique: false
      });
    }

image.png

阅读 212
avatarAI BotBETA

IndexedDB 的索引是逻辑层面的概念,并不会直接影响对象存储(ObjectStore)的物理存储结构。创建唯一索引和普通索引主要带来以下变化:

  1. 元数据层面
  2. 在数据库的 schema 元数据中会记录索引定义(名称、keyPath、是否唯一等)
  3. 可以通过 objectStore.indexNames 查看所有索引名称列表
  4. 数据约束层面
  5. 唯一索引会强制该字段值的唯一性(插入重复值时抛出 ConstraintError
  6. 普通索引允许重复值存在
  7. 查询能力层面
  8. 两种索引都会在底层创建对应的 B+Tree 结构用于加速查询
  9. 可以通过 index.get() 等 API 直接通过索引查询数据

你的示例中虽然创建了多个索引,但通过开发者工具查看时可能不会直观看到结构变化,这是因为:

  1. 索引数据是透明维护的,不需要手动管理
  2. 主键(uuid)已经自带唯一索引,再创建 uuid 的唯一索引其实是冗余的
  3. 开发者工具一般只会展示索引列表,不会展示底层数据结构变化

唯一性验证的差异示例:

// 唯一索引会报错
objectStore.add({uuid: 1, name: "Alice"}); 
objectStore.add({uuid: 1, name: "Bob"}); // 抛出 ConstraintError

// 普通索引允许重复
objectStore.add({name: "Alice", age: 20});
objectStore.add({name: "Alice", age: 25}); // 成功插入

建议在创建索引时:

  1. 主键字段无需额外创建唯一索引
  2. 根据查询需求创建必要索引(索引会增加写入开销)
  3. 唯一索引可用于强制业务数据唯一性约束
3 个回答
我亲测好像没有任何变化

所以你想要看到的“变化”是 DevTools 里能看到的,是这个意思吗?

image.png

这仨就是你建的索引啊……你点它们,右面数据会分别按你的索引来排序。

先介绍一下IndexedDB 是什么?
IndexedDB 是浏览器端的一种数据库,用于在客户端存储大量结构化数据。在 IndexedDB 中,对象仓库(Object Store)类似于传统数据库中的表 ,而索引(Index)用于加速数据的检索。

根据楼主的提供的信息来看,实际观察没有变化的原因可能有以下两种情况:

可视化工具局限:你通过浏览器开发者工具查看 IndexedDB 的结构时,可能因为工具的局限性,没有直观地展示出索引在内部结构上的变化。这些工具通常只是提供了一个简单的界面来查看对象仓库和其中的记录,而不会详细展示索引的底层数据结构和实现细节。

运行时动态变化:索引的创建和维护更多是在运行时动态进行的。在你创建索引后,数据库内部会根据数据的插入、更新和删除操作来动态调整索引结构。但从静态的仓库结构展示上,你可能无法直接观察到这些变化。

再有一个,验证索引是否生效的方法:
查询性能测试:可以通过插入大量数据,然后分别使用和不使用索引进行查询,对比查询的时间消耗。如果索引生效,使用索引的查询应该比不使用索引的查询快很多。
数据插入测试:尝试插入两条具有相同 uuid 值(唯一索引)的数据,观察是否会抛出唯一性冲突的错误。如果抛出错误,说明唯一索引的唯一性约束生效。

所以说,定义唯一索引和普通索引后,IndexedDB 在仓库的底层结构上是有变化的,只是在你使用的可视化工具中可能无法直观体现。

结构上:IndexedDB的Object Store在创建唯一索引或普通索引后,本身的结构(字段、记录)不会发生变化。这就是为什么你在开发者工具中没有看到明显的变化。

实际影响:索引主要影响数据操作(插入、更新、查询)和性能(查询速度、写操作开销、存储空间)。

建议:移除冗余的uuid索引,因为主键已经保证了唯一性。合理使用索引,避免创建不必要的索引,以减少性能开销。

优化后的

request.onupgradeneeded = function (e) {
  try {
    db = e.target.result;

    // 创建存储库
    var objectStore = db.createObjectStore('students', {
      keyPath: 'id',  // 字段名改为id,语义更清晰
      autoIncrement: true
    });

    // 创建必要的索引
    objectStore.createIndex('name', 'name', { unique: false }); // 假设需要按name查询
    objectStore.createIndex('age', 'age', { unique: false });   // 假设需要按age查询
  } catch (error) {
    console.error('数据库初始化失败:', error);
  }
};

// 错误处理
request.onerror = function (e) {
  console.error('打开数据库失败:', e.target.error);
};

// 成功打开数据库后插入初始数据(可选)
request.onsuccess = function (e) {
  db = e.target.result;
  let transaction = db.transaction(['students'], 'readwrite');
  let store = transaction.objectStore('students');
  store.add({ name: '张三', age: 23 }).onsuccess = function () {
    console.log('初始数据插入成功');
  };
};
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏