Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB在包含50000.000多个文档的大型集合上的写入性能较差_Mongodb - Fatal编程技术网

MongoDB在包含50000.000多个文档的大型集合上的写入性能较差

MongoDB在包含50000.000多个文档的大型集合上的写入性能较差,mongodb,Mongodb,我有一个MongoDB,它存储204.639.403项目的产品数据,这些数据已经按照项目所在国的不同,在同一个MongoDB进程中运行在同一台物理机器上的四个逻辑数据库中 以下是每个逻辑数据库的文档数列表: 国家:56.719.977 De:61.216.165 Fr:52.280.460 It:34.422.801 我的问题是,数据库写入性能越来越差,特别是对四个数据库中最大的数据库(De)的写入变得非常糟糕,根据iotop的说法,mongod进程使用99%的IO时间,每秒写入少于3MB,

我有一个MongoDB,它存储204.639.403项目的产品数据,这些数据已经按照项目所在国的不同,在同一个MongoDB进程中运行在同一台物理机器上的四个逻辑数据库中

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

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

每个数据库都有相同的数据和索引结构,我将使用最大的数据库(De)作为进一步的示例

这是从数据库中提取的随机项,正如示例所示,结构经过优化,可通过一次读取收集所有重要数据:

{
    "_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等级进行排序

这是来自最大数据库的统计信息:

{
    "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
}
值得一提的是,索引大小几乎是存储大小的一半

每个国家/地区的数据库每天必须处理300-500万次更新/插入,我的目标是在夜间不到五小时内执行写操作

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

我已经制定了一些优化策略:

  • 减少索引的数量:
    • 默认的_id可以使用ProductId,而不是默认的MongoId,这将为每个总尼克斯大小每DB节省6-7%
    • 试图删除Categories_1_RankA_-1索引,可能BrowseNodes_1_RankA_1_RankB_-1索引也可以处理查询。当不使用完整索引时,排序是否仍然执行良好?另一种方法是将索引匹配类别_1_RankA_1_RankB_-1存储在另一个引用主集合的集合中
  • 通过使用较小的键来减少原始数据量,而不是“Categories”、“Eans”、“new”…我可以使用“a”、“b”、“c”…这应该很容易,因为我使用了,但我现在不知道这有多值得
  • 将RAID1替换为RAID0,可以很容易地测试从机,重新安装并将其读取到副本集
  • 测试更强的硬件SSD和更多的内存,它们应该能够更快地处理读写操作
  • 使用MongoDB的着色功能:
    • 我读到每个碎片都必须保存整个数据库索引
    • 我担心查询结构可能不适合共享环境。使用产品id作为分片键似乎并不适合所有查询类型,按类别分片也很复杂。单个项目可以在多个主类别和子类别中列出。我的担心可能是错误的,我从未在生产环境中使用过它
但是应该还有其他的优化策略,我也没有想到我想听到的

哪一种优化策略听起来最有希望,或者是需要几种优化的混合?

最有可能的是,由于创纪录的增长,您遇到了问题,请参阅


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

你会考虑使用一个支持文档的吞吐量更好的数据库吗?我听过很多成功的故事。而且(我是工程师的地方)在高并发写负载和大文档方面具有非常好的性能。很高兴回答有关FoundationDB的更多问题。

出于历史原因,值得注意的是,其中包含了与此问题相关的讨论。填充因子为1(无填充),我现在尝试使用usePower2Sizes标志:``db.runCommand({collMod:“Item”,usePower2Sizes:true}``填充对写入有很大的影响,但除了填充之外,索引也得到了优化。这两种优化对写性能都有很大的影响优化索引:4:47用于250万次更新-优化索引和填充:1:15用于150万次更新-无任何优化:9:17用于120万次更新我要优化的下一步是IOPS,目前我正在测试RAID0,下一步将把日志移到另一个硬盘上。你到底是如何优化索引的?谢谢,我从来没有听说过TokuMX,但我尝试一下。关于FoundationDB seeems为键/值