1

MongoDB で非常に遅い挿入 (挿入あたり約 200 秒) を経験していますが、その理由はまったくわかりません。

匿名化されたユーザー名 (int)、匿名化されたコメント ID (int)、およびコメントの CSV ファイルがあります。これらはすべて文字列として読み込まれますが、最初の 2 つのフィールドは問題なく int にキャストできます。

データベースには 1 億レコードのコレクションが含まれており、現在、別のコレクションに書き込まれるコメント ID を使用してユーザーのマッピングを作成しようとしています。1 億のコメントが配布されているユーザーは、およそ 6 万人です。つまり、ユーザーごとに 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

このコードで確認できる唯一の速度低下の原因は、挿入ごとに新しい接続が作成されることです。ただし、1 つの接続を使用して 500 個のドキュメントのバッチを挿入しようとすると (単一ドキュメント挿入と複数ドキュメント挿入の両方を使用)、さらに時間がかかります。このコードを順番に実行しています。

誰かがより良い提案をしていますか?

MongoDB バージョン: v3.4.9

PyMongo バージョン: 3.5.1

Python バージョン: 3.5.3

OS: Ubuntu 17.4

4

1 に答える 1

2

挿入自体は非常に高速である可能性が高く、ループの他の部分が遅い可能性があります。「user_id」がインデックス化されていない場合、これがおそらく遅い部分です。

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

「data」コレクションの user_id にインデックスを作成します。これを一度だけ実行してください:

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

これには数分かかる場合がありますが、その後は「find_one」がはるかに高速になります。

また、挿入ごとに新しい MongoClient を作成します。これにより、コードも少し遅くなります。プログラムの実行中に MongoClient を 1 回作成します。「write_user」関数でローカル変数ではなく、グローバル変数として宣言します。

于 2017-10-18T08:08:29.730 に答える