mongoDB没有选择索引

Posted

技术标签:

【中文标题】mongoDB没有选择索引【英文标题】:mongoDB not picking index 【发布时间】:2022-01-21 23:39:06 【问题描述】:

我有一个如下的 mongoDB 查询。

    db.mobiles.find(
  $or: [
    
      status: "roaming"
    ,
    
      status: "local"
    ,
    
      inUse: true
    ,
    
      available: true
    ,
    
      color: true
    
  ],
  updatedAt: 
    $lte: 1639992579831
  
)

我创建了如下索引

db.mobiles.createIndex(  “status” : 1 ,   “inUse” : 1 ,  “available” : 1 ,  “color” : 1 , “updatedAt” :  -1 )

当我执行 explain() 时,我没有看到索引被使用。难道我做错了什么。 ?

我可以看到在我执行db.mobiles.getIndexes()时创建了索引

【问题讨论】:

【参考方案1】:

https://docs.mongodb.com/manual/core/index-compound/#prefixes 读作:

对于复合索引,MongoDB 可以使用索引来支持对索引前缀的查​​询。

db.mobiles.createIndex(  “status” : 1 ,   “inUse” : 1 ,  “available” : 1 ,  “color” : 1 , “updatedAt” :  -1 )

是一个复合索引,因此唯一可以从中受益的查询是至少具有“状态”谓词的查询。

您的查询确实有它,但在 $or 语句中,意味着您很乐意选择具有 status 的文档,只要至少有 1 个其他 $or 条件匹配,例如颜色。在这种情况下,mongo 无法使用该字段在索引中进行搜索。

这是它在 explain() 输出中的样子:

"parsedQuery": 
  "$and": [
    
      "$or": [
        
          "$or": [
            
              "available": 
                "$eq": true
              
            ,
            
              "color": 
                "$eq": true
              
            ,
            
              "inUse": 
                "$eq": true
              
            
          ]
        ,
        
          "status": 
            "$in": [
              "local",
              "roaming"
            ]
          
        
      ]
    ,
    
      "updatedAt": 
        "$lte": 1639992579831
      
    
  ]
,

但这不是故事的全部。查询计划器分析诸如索引选择性之类的参数。考虑到它是一个布尔值,没有太多选项,并且对于正态分布,它必须像一半的集合符合条件。在这种情况下使用索引并没有太大的好处。

考虑到查询,唯一有意义的索引是updatedAt:

db.mobiles.createIndex(  “updatedAt” :  -1 )

【讨论】:

以上是关于mongoDB没有选择索引的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb笔记 Index

mongoDB 索引

mongoDB_08索引的操作

最简单方式理解为什么MongoDB索引选择B-树,而 Mysql 选择B+树

MongoDB + C#:未选择/使用 GUID 字段上的复合索引

MongoDB-6: MongoDB索引