MST

星途 面试题库

面试题:MongoDB索引优化的复杂场景及策略

在一个高并发读写的MongoDB集群环境中,集合的数据量非常大,并且存在多种复杂的查询场景,包括范围查询、多字段联合查询以及排序操作。请详细阐述你会采取哪些策略来创建和优化索引,以确保系统在高负载下仍能保持良好的性能,同时还要考虑到索引维护成本对系统整体性能的影响。
29.4万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

1. 分析查询场景

  • 范围查询:对于范围查询,例如查询某个时间段内的数据,若 created_at 字段用于此查询,应在该字段上创建单字段索引。例如在Python的 pymongo 中:collection.create_index([("created_at", pymongo.ASCENDING)])
  • 多字段联合查询:如果有查询条件是多个字段的组合,如按 categoryprice 联合查询,应创建复合索引。复合索引字段顺序很重要,将选择性高(基数大)的字段放在前面。在 pymongo 中:collection.create_index([("category", pymongo.ASCENDING), ("price", pymongo.ASCENDING)])
  • 排序操作:若经常按某个字段排序,如按 views 字段降序排序,需在该字段创建索引。若排序字段同时参与范围查询,可考虑合并到复合索引中。例如:collection.create_index([("views", pymongo.DESCENDING)])

2. 索引覆盖

  • 尽量使用索引覆盖查询,即查询的字段都包含在索引中,这样MongoDB无需回表获取数据,能大大提高查询性能。例如查询 titleviews 字段,可创建复合索引 [("title", pymongo.ASCENDING), ("views", pymongo.ASCENDING)],若查询条件允许,可提高性能。

3. 避免冗余索引

  • 冗余索引会增加存储和维护成本。例如已经有复合索引 [("a", 1), ("b", 1)],就无需再创建单字段索引 [("a", 1)],因为复合索引已覆盖单字段索引功能。通过 db.collection.getIndexes() 查看现有索引,避免创建冗余索引。

4. 索引维护时机

  • 批量操作时:在进行大量数据插入、更新或删除操作前,若可能,先删除不必要索引,操作完成后再重建。这样可减少索引维护开销,因为批量操作时索引维护成本高。
  • 定期优化:定期使用 db.collection.reIndex() 对集合重建索引,以优化索引结构,尤其是在数据量大幅变化或索引碎片化严重时。但此操作会占用较多资源,应选择系统低峰期执行。

5. 索引选择性评估

  • 使用 db.collection.stats().indexDetails 查看索引选择性,选择性越高,索引效果越好。对于选择性低的索引,评估是否有必要保留,因为低选择性索引可能增加维护成本却对性能提升有限。

6. 分片与索引

  • 在分片集群中,合理选择分片键很重要。若分片键选择不当,可能导致数据分布不均,影响查询性能。同时,确保索引与分片策略配合,例如在片键上创建索引,可提高跨分片查询性能。