我有一个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的着色功能:
但应该还有其他优化策略,我也不想听到