我有一个MongoDB,它存储了204.639.403个商品的产品数据,这些数据已经按照商品的国家,在同一个MongoDB过程中,在同一台物理机器上运行four logical个数据库.

以下是每个逻辑数据库的文档数列表:

  • 库克:56.719.977
  • 德:61.216.165
  • Fr:52.280.460
  • 它:34.422.801

我的问题是,数据库的写入性能越来越差,尤其是对四个数据库中最大的数据库(De)的写入变得非常糟糕,根据iotop,mongod进程使用了99%个IO时间,每秒写入少于3MB,读取少于1.5MB.这会导致长时间锁定数据库,100%+锁根据mongostat变得正常——即使所有写入和读取其他国家/地区数据库的进程都已停止.当前从机的负载高达6,副本集主机的负载同时为2-3,因此也会导致复制延迟.

每个数据库都有相同的数据和索引 struct ,我使用最大的数据库(De)只是为了进一步的示例.

这是一个从数据库中随机抽取的项目,正如示例所示,该 struct 经过优化,可以通过一次读取收集所有重要数据:

{
    "_id" : ObjectId("533b675dba0e381ecf4daa86"),
    "ProductId" : "XGW1-E002F-DW",
    "Title" : "Sample item",
    "OfferNew" : {
        "Count" : 7,
        "LowestPrice" : 2631,
        "OfferCondition" : "NEW"
    },
    "Country" : "de",
    "ImageUrl" : "http://….jpg",
    "OfferHistoryNew" : [ 
        … 
        {
            "Date" : ISODate("2014-06-01T23:22:10.940+02:00"),
            "Value" : {
                "Count" : 10,
                "LowestPrice" : 2171,
                "OfferCondition" : "NEW"
            }
        }
    ],
    "Processed" : ISODate("2014-06-09T23:22:10.940+02:00"),
    "Eans" : [ 
        "9781241461959"
    ],
    "OfferUsed" : {
        "Count" : 1,
        "LowestPrice" : 5660,
        "OfferCondition" : "USED"
    },
    "Categories" : [ 
        NumberLong(186606), 
        NumberLong(541686), 
        NumberLong(288100), 
        NumberLong(143), 
        NumberLong(15777241)
    ]
}

典型的查询形式很简单,比如按ProductId或EAN,只按类别进行细化,并按其A等级或按类别和A等级范围(例如1到10.000)进行细化,并按B等级进行排序.

以下是最 Big Data 库的统计数据:

{
    "ns" : "De.Item",
    "count" : 61216165,
    "size" : 43915150656,
    "avgObjSize" : 717,
    "storageSize" : 45795192544,
    "numExtents" : 42,
    "nindexes" : 6,
    "lastExtentSize" : 2146426864,
    "paddingFactor" : 1,
    "systemFlags" : 0,
    "userFlags" : 1,
    "totalIndexSize" : 41356824320,
    "indexSizes" : {
        "_id_" : 2544027808,
        "RankA_1" : 1718096464,
        "Categories_1_RankA_1_RankB_-1" : 16383534832,
        "Eans_1" : 2846073776,
        "Categories_1_RankA_-1" : 15115290064,
        "ProductId_1" : 2749801376
    },
    "ok" : 1
}

值得一提的是,索引大小是nearly half of the storage size.

每个国家的DBhas to handle 3-5 million updates/inserts per day,我的目标是在晚上不到五个小时内执行写操作.

目前,它是一个带有两台服务器的复制集,每台服务器都有32GB的RAM和一个带有2TB硬盘的RAID1.诸如死锁调度器和noatime之类的简单优化已经完成.

我制定了一些优化策略:

  • 减少索引的数量:
      • 通过使用较小的键来减少原始数据量,而不是"Categories"、"Eans"、"new"……我可以使用"a"、"b"、"c"……这应该很容易,因为我使用了http://mongojack.org/,但我现在不知道这有多划算.
      • 用RAID0替换RAID1,可以很容易地测试从机,重新安装并读取副本集.
      • 测试更强大的硬件SSD和更多内存,它们应该能够更快地处理读写操作.
      • 使用MongoDB的着色功能:

          但应该还有其他优化策略,我也不想听到

          推荐答案

          最有可能的情况是,由于创纪录的增长,您遇到了问题,请参阅http://docs.mongodb.org/manual/core/write-performance/#document-growth.

          Mongo更喜欢固定(或至少有界)大小的记录.将记录大小增加到预先分配的存储空间之外,会导致文档移动到磁盘上的另一个位置,每次写入都会增加I/O.如果你的文档大小相对均匀,考虑为插入的平均文档预先分配"足够"的空间.否则,考虑将快速增长的嵌套数组分割成单独的集合,从而用插入替换替换.还要判断碎片,并考虑不时压缩数据库,这样每个区块有更高的文档密度,从而减少硬页面故障.

          Mongodb相关问答推荐

          在MondoDB中:将对象数组从切片索引数组切片,并通过聚合推入数组

          更新值导致错误 Golang MongoDB

          为什么使用 Golang Mongo 驱动程序进行简单查询需要超过 2 秒?

          如何更新mongo中列表最后一个对象的属性

          找到一个用户,然后使用 MongoDB 根据他们的总分获得他们的排名

          如何过滤查找mongodb的结果

          MongoDb c# driver LINQ vs Native 查询

          使用绝对类型在 Typescript 中编写 Mongoose 的类型化模型和模式的类和接口

          如何将记录从一个 mongo 数据库插入另一个?

          指定字段对于 MongoDB 是transient瞬态的,但对于 RestController 不是

          Node.js 和 Passport 对象没有方法 validPassword

          Clojure 和 NoSQL 数据库

          MongoDB 存储 ObjectId 的数组

          Python - Pymongo 插入和更新文档

          如何使用 MongoDB 以编程方式预拆分基于 GUID 的分片键

          查询不等于 null 或空的地方

          验证 MongoCredential 的异常和未分类的 Mongo Db 异常

          spring 数据MongoDB.生成id的错误

          是否可以在 Mongodb 中的两个数据库之间进行 $lookup 聚合?

          MongoDb - 利用多 CPU 服务器进行写入繁重的应用程序