• mongodb ISODate问题(大量数据update优化)


    问题描述:

      上周有个需求,把mongodb中birthday (ISO日期格式) 转换成北京时间,并保存成string类型。

    最初思路:

      遍历查找出的结果,逐个加8小时,然后通过_id逐个去update_one。但是发现这种方式效率太低了,一分钟才能更新一千五百条数据。

      

    # -*- coding: utf-8 -*-
    from pymongo import MongoClient
    import time
    import datetime
    
    
    def init():
        myclient = MongoClient(host='*.*.*.*', port=27117)
        # admin为登陆校验库
        auth_db = myclient.admin
        auth_db.authenticate('admin', '1234')
        # 连接库
        mydb = myclient['SR_123']
        mycol = mydb['Data_170724145755025001_0305_copy4']
        print(time.time())
        count = 0
        # 只取有birthday的数据,且只返回_id和birthday
        for x in mycol.find({'birthday':{'$exists': True}},{'_id','birthday'}):
            count = count + 1
            print(count)
            _time = x.get('birthday')
            _time += datetime.timedelta(hours=8)
            timeStr = _time.strftime("%Y%m%d")
            _id = x.get('_id')
            query1 = {"_id": _id}
            newvalues = {"$set": {"birthdayStr": timeStr}}
            mycol.update_one(query1, newvalues)
        print(time.time())
    
    init()
    View Code

    新的思路:  

      通过birthday去重,然后通过birthday去update_many

     for x in mycol.find().distinct('birthday'):
            _time1 = x + datetime.timedelta(hours=8)
            timeStr = _time1.strftime("%Y%m%d")
            query1 = {"birthday": x}
            newvalues = {"$set": {"birthdayStr": timeStr}}
            mycol.update_many(query1, newvalues)
    

      

    最终思路:

      利用mongodb 的批量操作bulk_write,并且控制每次批量的数量,避免拼接过长报错。最终发现这种方式,当数据多的时候,效率远比上面两种方式快

    # -*- coding: utf-8 -*-
    from pymongo import MongoClient
    from pymongo import UpdateOne
    import time
    import datetime
    
    
    
    def init():
        myclient = MongoClient(host='*.*.*.*', port=27117)
        # admin为登陆校验库
        auth_db = myclient.admin
        auth_db.authenticate('admin', '1234')
        # 连接库
        mydb = myclient['SR_123']
        mycol = mydb['Data_170724145755025001_0305_copy4']
        print(time.time())
        testList = []
        i = 0
        aa=mycol.find({'birthday': {'$exists': True}},{'_id','birthday'})
        for x in aa:
            i = i + 1;
            _time = x.get('birthday')
            _time += datetime.timedelta(hours=8)
            try:
                timeStr = _time.strftime("%Y%m%d")
            except:
                print(x)
            _id = x.get('_id')
            query1 = {"_id": _id}
            newvalues = {"$set": {"birthdayStr": r''+timeStr}}
            op = UpdateOne(query1, newvalues, upsert=True)
            testList.append(op)
            if( i % 50 == 0):
                print(i)
                mycol.bulk_write(testList, ordered=False, bypass_document_validation=True)
                testList.clear()
    
    
    init()
    

      

  • 相关阅读:
    [改善Java代码]使用构造块精炼程序
    [改善Java代码]若有必要,使用变长数组
    [改善Java代码]警惕数组的浅拷贝
    [改善Java代码]在明确的场景下,为集合指定初始容量
    [改善Java代码] 枚举项数量限定为64个以内
    [改善Java代码]多种最值算法,适时选择
    [改善Java代码]推荐使用枚举定义常量
    [改善Java代码]性能考虑,数组是首选
    [改善Java代码]用偶判断,不用奇判断
    [改善Java代码]break万万不可忘
  • 原文地址:https://www.cnblogs.com/cjh1111/p/10751845.html
Copyright © 2020-2023  润新知