面试题答案
一键面试普通索引对写操作性能影响原理
- 原理:
- 当在MongoDB中创建普通索引时,每次执行写操作(插入、更新等),数据库不仅要将数据写入集合,还要更新索引结构。普通索引允许重复值,其结构类似B - 树(通常情况下)。写操作时,MongoDB需要在索引结构中找到合适的位置插入或更新索引项,这涉及到树结构的遍历、节点分裂(如果空间不足)等操作,增加了额外的I/O和CPU开销。
- 举例 - 插入操作:
- 假设我们有一个集合
users
,包含name
字段,我们为name
字段创建了普通索引。
db.users.createIndex({name: 1});
- 当执行插入操作
db.users.insert({name: "John", age: 30})
时,除了将文档插入users
集合,MongoDB还需要在name
字段的普通索引中找到合适位置插入新的索引项(John
)。如果索引树节点已满,可能需要进行节点分裂操作,这会增加写操作的时间。
- 假设我们有一个集合
- 举例 - 更新操作:
- 若执行
db.users.update({name: "John"}, {$set: {name: "Jane"}})
,MongoDB不仅要更新集合中的文档,还要在name
索引中找到John
对应的索引项并更新为Jane
。这可能涉及到索引树中节点的移动等操作,同样会增加性能开销。
- 若执行
唯一索引对写操作性能影响原理
- 原理:
- 唯一索引与普通索引类似,在写操作时需要更新索引结构。但唯一索引的特殊性在于它不允许重复值。所以在每次写操作时,除了常规的索引更新操作,MongoDB还需要额外检查新值是否与已有值重复。这种唯一性检查增加了额外的查询操作,进一步增加了写操作的开销。并且,如果唯一性检查失败(插入重复值),整个写操作会失败并回滚。
- 举例 - 插入操作:
- 为
users
集合的email
字段创建唯一索引:
db.users.createIndex({email: 1}, {unique: true});
- 当执行
db.users.insert({email: "john@example.com", age: 30})
时,MongoDB首先检查email
索引中是否已有john@example.com
。若没有,才会将新文档插入集合并更新索引;若已有,则插入操作失败。这种额外的唯一性检查增加了插入操作的时间。
- 为
- 举例 - 更新操作:
- 执行
db.users.update({email: "john@example.com"}, {$set: {email: "jane@example.com"}})
时,MongoDB不仅要更新集合文档和email
索引,还要检查jane@example.com
在email
索引中是否已存在。若存在,更新操作失败,这比普通索引的更新操作多了唯一性验证步骤,增加了性能开销。
- 执行
总体而言,无论是普通索引还是唯一索引,都会增加写操作的性能开销,因为写操作不仅要处理数据本身,还要更新索引结构,唯一索引由于唯一性检查,开销相对更大。在设计数据库时,需要根据实际业务需求权衡索引带来的读性能提升和写性能下降之间的关系。