PyMongo用~100M记录插入难以忍受的慢速数据库

时间:2017-10-18 01:22:28

标签: python mongodb pymongo pymongo-3.x

我在MongoDB中遇到极慢的插入(大约200秒/插入),我不确定为什么。

我有一个匿名用户名(ints),匿名评论ID(整数)和评论的CSV文件。所有这些都以字符串形式读入,但前两个字段可以强制转换为整数。

数据库包含100M记录的集合,现在正在尝试使用其注释ID构建映射用户,该用户将写入另一个集合。 大约有60,000个用户在其上分发了100M评论。即为每个用户构建user_id = [comment_id0,...,comment_idN]并将其插入数据库,以便更快地获取所有用户注释。

def save_user_comments(dataset):
    usrs = defaultdict(list)
    updatebar = tqdm(total = 100000000, desc = 'Generating user-comment map', leave = False)
    pool = mp.Pool()

    for i, (user_id, comment_id, _) in enumerate(dataset):
        usrs[str(user_id)].append(comment_id)
        updatebar.update(1)

    prev = 0
    keys, vals = list(usrs.keys()), list(usrs.values())
    results = pool.map_async(write_user, zip(keys, vals)).get()

progbar = tqdm(total = 67377, desc = 'Users Inserted', leave = False )
def write_user(itempair):
    usr, comments = itempair

    db = MongoClient(host = some_ip, port = some_port).GenderSpectrum
    table = db.user

    if db.user.find_one({'user_id': str(usr)}):
        progbar.update(1)
        return

    u_obj = {}
    obj = db.data.find_one({'user_id': str(usr)})

    u_obj['comment_ids'] = comments
    u_obj['_id'] = str(usr)
    u_obj['is_female'] = obj['is_female']
    u_obj['user_id'] = str(usr)
    db.user.insert_one(u_obj)
    progbar.update(1)
    return 1

我在此代码中可以看到的唯一可以减慢速度的事情是为每个插入创建一个新连接。但是,尝试使用一个连接(使用单个和多个文档插入)插入500个文档的批次甚至更慢。所以顺序运行此代码。

有人有更好的建议吗?

MongoDB版本:v3.4.9

PyMongo版本:3.5.1

Python版本:3.5.3

操作系统:Ubuntu 17.4

1 个答案:

答案 0 :(得分:2)

插入本身可能非常快,似乎很可能你的循环的其他部分很慢。如果" user_id"没有索引,那么这可能是缓慢的部分:

db.data.find_one({'user_id': str(usr)})

在"数据"中创建一个关于user_id的索引。采集。只做一次:

db.data.create_index([('user_id', 1)])

这可能需要几分钟,之后" find_one"会更快。

您还为每个插件创建一个新的MongoClient,这也会使代码慢一点。在程序的持续时间内创建一次MongoClient:将其声明为全局变量,而不是#34; write_user"中的局部变量。功能