提高MongoDB的收集效率

时间:2018-07-01 19:04:34

标签: mongodb performance amazon-ec2 pymongo database-performance

我有一个MongoDB集合,其中包含大约20M个对象。每晚,我要删除几个财务月的数据,并用Django从PyMongo 3.0.something的CSV导入文件中替换它们。随着数据库的增长,此导入将花费更长的时间,并且服务器和进程有时会开始冻结。在我们的AWS服务器上,仅删除操作(600万行)就开始耗时约14分钟。我已经按日期对删除进行了索引,这是适当的字段。

我要删除的查询是:

db.getCollection("x").remove({date: {$gte: ISODate('2018-04-01')}})

与Pymongo集成的顶级代码可能会略有内存泄漏,它是:

        while keep_fetch:
            raw_data = input_adapter.get_bulk() # in practice pulling 100,000 lines.
            if raw_data is None:
                raise Exception("bulk of data didn't return due to error,remove all last inserted docs")
            if raw_data == {} or raw_data == [] :
                log.debug("no more data to fetch")
                keep_fetch = False
                break
            #check for maintenance before insert first bulk
            if first_bulk == True: # first run-through, execute a delete if there is data.
                first_bulk = False
                #clean data in db to avoid duplicates
                if 'maintain_before_insert' in dir(output_adapter):
                    # Call function that cleans a time period's data from the database, and does other maintenance.
                    if output_adapter.maintain_before_insert() == False:
                        raise Exception("collection maintenance failed") 
            #Run an input adapter that formats the data into a list for insertion into Mongo.
            list_docs=input_adapter.format_data( raw_data )
            #get last date for next task to start from
            last_date = max(list_docs, key=lambda x:x['date'])['date']           
            output_adapter.store_bulk( list_docs ) # Mongo insert; it uses unmodified insert_many on the collection
            gc.collect()

我很好奇如何加快处理速度。我尝试了批量删除,但没有任何改善。我对即将到期的索引感到好奇,但是我不知道当我们的进口过时时,即将到期的索引是否可以停止(在拖欠了整整三个月之后,它回落到2,并且每天增加一天的大小)

增加的AWS服务器大小似乎并不影响流程速度。我们正在使用Django / Python服务器来发送删除和插入查询,插入和删除过程似乎花费相同的时间。

服务器没有交换文件;可能是服务器设置问题,因此更适合ServerFault,但由于有可能出现代码错误,我在这里询问。

我已经进行了大量研究,并尝试了几种可能性。升级我们的PyMongo版本会有所帮助吗?

过程数据,过程1

插入单个(〜675 MiB)CSV文件时的性能指标: 从S3存储桶下载文件:.45秒 删除记录(4月未完成):在14:18中删除了6,200,000条记录 记录存储:100,000条记录,每11-12秒之间插入一次[注意:在删除之前,先将100,000条记录加载到Python内存中,所以数字并不准确] 20:15:21和20:32:11,总共添加了16:50和6,798,155条记录

后处理表大小:计数:19,367,660;大小:7.5 GiB,存储大小:3.6 GiB,索引:2,总索引大小:486.3 MiB

过程数据,过程2

插入单个(〜225 MiB)CSV文件的性能指标: 从S3存储桶下载文件:0.5秒 删除记录(4月未完成):在2:51中删除了2,399,827条记录 记录存储:在每15秒之间插入100,000条记录[注意:删除前先将100,000条记录加载到Python内存中,因此数字并不准确] 20:37:10和20:43:37,总共6:27和2,417,669条记录已添加

后处理表大小:计数:6,332,293;大小:2.5 GiB,存储大小:1.1 GiB,索引:3,总索引大小:264.3 MiB

过程数据,过程3

插入单个(〜20 MiB)CSV文件的性能指标: 从S3存储桶下载文件:.03秒 删除记录(4月未完成):在22秒内删除了341,317条记录 记录存储:100,000记录之间每21秒钟插入一次[注意:在删除之前,第100,000条记录已加载到Python内存中,因此数字并不准确] 20:44:46和20:45:17,总共0:31和349,100条记录添加了

后处理表大小:计数:811,200;大小:145.7 MiB,存储大小:75.6 MiB,索引:3,总索引大小:23.4 MiB

过程数据,过程4

插入单个(〜20 MiB)CSV文件的性能指标: 从S3存储桶下载文件:0.5秒 删除记录(4月未完成):在:09中删除了352,010条记录 记录存储:100,000个记录之间每8秒钟插入一次[注意:在删除之前,第100,000个记录已加载到Python内存中,因此数字并不准确] 20:46:05和20:46:38,总共0:33和357,040条记录添加了

后处理表大小:计数:821,924;大小:217.7 MiB,存储大小:95.3 MiB,索引:3,总索引大小:22.9 MiB

注意

删除后的性能似乎极度非线性。看起来非常像我应该在重新索引之前以某种方式批处理删除操作,但我不是。我可以以某种方式“锁定”该集合以进行删除和添加(除此过程外没有使用)或创建单个事务以防止索引重新计算中间过程,以便事后重新计算?

请求的信息:

1)我们的服务器是EC2实例,在Django / Python端运行18.04,在Mongo端运行14.04。 Mongo版本是3.4.3 Wired Tiger引擎。

2)我已经检查了explain()输出,并且JSON输出看起来像这样:

    "winningPlan" : {
        "stage" : "FETCH", 
        "inputStage" : {
            "stage" : "IXSCAN", 
            "keyPattern" : {
                "date" : -1.0
            }, 
            "indexName" : "date_-1", 
            "isMultiKey" : false, 
            "multiKeyPaths" : {
                "date" : [

                ]
            }, 
            "isUnique" : false, 
            "isSparse" : false, 
            "isPartial" : false, 
            "indexVersion" : 2.0, 
            "direction" : "forward", 
            "indexBounds" : {
                "date" : [
                    "[new Date(9223372036854775807), new Date(1522540800000)]"
                ]
            }
        }

我的结论是索引正在工作。

3)索引“日期”字段和“标识”字段

4)Mongo端上的当前硬件是t2.small或t2.medium Mongo服务器。将实例从t1升级到t2似乎对删除速度几乎没有影响,尽管中型服务器没有冻结,这很好。

5)每个驱动器的卷都是基于云的gp2 AWS实例。理论上有160 MiB / s的限制,我要添加的行总计为7.5GiB,索引大小为486.3MB。

0 个答案:

没有答案