面试题答案
一键面试索引创建与性能优化
- 避免过多索引:
- 原因:每个索引都会占用额外的磁盘空间,并且在数据写入时,MongoDB需要更新所有相关索引,这会增加写操作的开销。过多索引会导致磁盘I/O和内存压力增大,降低写性能。
- 案例:假设一个电商订单系统,订单集合存储订单信息。如果对订单的每个字段都创建索引,如订单号、客户ID、下单时间、商品ID等。当有新订单写入时,MongoDB需要同时更新多个索引,写入速度会明显下降。特别是在高并发写入场景下,过多索引会成为性能瓶颈。
- 根据查询模式设计索引:
- 单字段查询:如果经常根据单个字段进行查询,如根据用户ID查询用户信息。例如,在社交媒体应用中,经常根据用户ID查询用户的详细资料。可以创建单字段索引,示例代码如下:
db.users.createIndex({ userId: 1 });
- 复合查询:对于涉及多个字段的查询,要创建复合索引。例如,在电商订单查询中,经常根据下单时间和客户ID查询订单。复合索引的顺序很重要,要按照查询条件的选择性(过滤数据量的能力)从高到低排序。
db.orders.createIndex({ orderTime: 1, customerId: 1 });
- 覆盖索引:当查询的字段都包含在索引中时,可以使用覆盖索引。这可以避免回表操作(即从索引找到数据后,再到文档中获取完整数据),提高查询性能。例如,只查询用户的用户名和邮箱,而这两个字段在索引中:
db.users.createIndex({ username: 1, email: 1 });
// 查询
db.users.find({ username: "exampleUser" }, { username: 1, email: 1, _id: 0 });
索引标识与性能优化
- 索引标识查看:可以使用
db.collection.getIndexes()
命令查看集合上的所有索引。了解集合上已有的索引,可以避免重复创建相同功能的索引,也有助于分析当前索引是否满足查询需求。 - 索引标识与查询计划:通过
explain()
方法查看查询计划,其中会显示使用的索引。例如:
db.orders.find({ orderTime: { $gte: ISODate("2023 - 01 - 01") } }).explain("executionStats");
分析查询计划中显示的索引使用情况,如果未使用预期索引,可能需要调整索引设计或查询语句。
索引修改与性能优化
- 重建索引:如果索引损坏或碎片化严重,可以重建索引来提高性能。例如:
db.collection.reIndex();
重建索引会删除旧索引并创建新索引,整理索引结构,减少碎片化,提高查询性能。
2. 删除无用索引:定期检查索引使用情况,删除不再使用的索引。例如,可以通过监控查询日志,分析哪些索引长时间未被使用。然后使用db.collection.dropIndex({ indexName: 1 });
命令删除无用索引,减少索引维护开销,提高写性能。