1

我在 windows server 2008 R2 上使用 MongoDB,版本 2.4.8,我有奇怪的索引行为,我无法解释。这是我收藏中的结构示例:

{
    "_id" : NUUID("67070100-4627-4aa5-8ab9-45624e5b82ad"), 
    "PropertyType" : "Cooperative",
    "Address" : {
        "Street" : "aaaaaaaaa",
        "HouseNo" : "165",
        "PostalCode" : 2860,
        "City" : "bbbbb",
        "Floor" : "1",
        "DoorNumber" : ""
    },
    "Sales" : {
        "Price" : 425000,
        "Payout" : 0,
        "AreaPrice" : 9042,
        "GrossPrice" : 2340,
        "NetPrice" : 800,
    },
    "WithdrawnFromSale" : true,
    "UnitData" : {
        "UnitType" : "aaaaa",
        "Area" : 400,
        "LivingArea" : 50,
        "UnitArea" : 50,
        "Rooms" : 2,
        "BuildYear" : 1948,
        "GroundArea" : 203,
        "NoiseLevel" : 5
    }
}

另外,我为该集合创建了索引:

db["UnitModel"].ensureIndex({ "Sales": 1, "PropertyType": 1, "UnitData.Rooms": 1, "UnitData.NoiseLevel": 1 })

该索引的问题是我在使用该索引时得到了错误的项目计数。

当我发出这个请求时:

db.UnitModel.find({Sales: {$ne: null}, WithdrawnFromSale: false}).explain({verbose: true})

我得到以下结果:

{
    "cursor" : "BtreeCursor Sales_1_PropertyType_1_UnitData.Rooms_1_UnitData.NoiseLevel_1 multi",
    "isMultiKey" : false,
    "n" : 19368,
    "nscannedObjects" : 42875,
    "nscanned" : 42876,
    "nscannedObjectsAllPlans" : 43274,
    "nscannedAllPlans" : 43276,
    "scanAndOrder" : false,
    "indexOnly" : false,
    ....
}

在这里我们可以看到已经使用了索引,但是返回的项目数是“n”:19368。。这是错误的。它应该是 70986项符合该标准的集合。

为什么我确定应该是更多记录?好吧,这里的代码:

var totalCount = 0;
db.UnitModel.find({WithdrawnFromSale: false}).forEach(
  function (e) {      
    if(e.hasOwnProperty('Sales') && e.Sales != null)
      totalCount++;
  }
)
totalCount;

总数 = 70986

为了确保上面的查询不使用任何索引,让我们检查一下:

db.UnitModel.find({WithdrawnFromSale: false}).explain({verbose: true})

结果:

{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 70986,
    "nscannedObjects" : 3204212,
    "nscanned" : 3204212,
    "nscannedObjectsAllPlans" : 3204212,
    "nscannedAllPlans" : 3204212,
    "scanAndOrder" : false,
    "indexOnly" : false,
    ....
}

因此,对于我正在使用的 UnitModel 集合,标准:Sales: {$ne: null}, WithdrawnFromSale: false它应该是 mongo 返回的 70986 条记录。但正如你所看到的,我弄错了。

有人可以解释我为什么吗?可能是什么原因?

顺便提一句。当我删除该索引并使用以下索引时: db["UnitModel"].ensureIndex({ "WithdrawnFromSale": 1}) 它按预期工作。但是我不需要那个索引,这对我的情况来说不是最优的。

4

2 回答 2

2

在 MongoDB 2.4 中,索引值的最大大小为 1024 字节。键太大而无法索引的当前行为是在服务器端记录警告——但这不会引发异常。在这种情况下,key 过长的文档在 key 过长时不会包含在索引中,而是会包含在其他索引中。这可能会导致结果不一致,例如计数不正确和“丢失的文档”无法通过一个索引找到,但可能在另一个索引或$natural搜索中可用。

在 MongoDB 2.5 开发/不稳定分支中(将在今年晚些时候的 MongoDB 2.6 生产版本中达到高潮)这种行为已经改变。在 MongoDB 2.5.5 中,如果插入/更新包含索引更新,其中键太大,则会引发异常。有关更多详细信息,请参阅MongoDB 问题跟踪器中的SERVER-5290

于 2014-01-15T22:31:19.553 回答
0

找出问题的原因。当我查看 monogodb 的日志文件时,我看到了大量以下消息:

HBReadModel.system.indexes Btree::insert: key 太大而无法索引,跳过 HBReadModel.UnitModel.$Sales_1_WithdrawnFromSale_1_PropertyType_1_UnitData.Rooms_1_UnitData.NoiseLevel_1

我试图在实际文档而不是字段中的销售字段上创建索引。为了避免这种情况,我只是重新创建了索引并在销售文档中指定了字段。日志清晰,查询按预期返回记录。

于 2014-01-14T12:38:52.557 回答