处理数百万个图像文件并将每个文件插入mongodb

问题描述

我在S3上收集了大量的图像文件(约800,000张图像,总大小超过1TB),我使用一些Python代码将其处理成字典以插入到MongoDB中。字典包含一个缓冲区,np.frombuffer之类的命令可使用该缓冲区来重建图像。

我需要处理每个文件并将其插入MongoDB。到目前为止,我已经尝试过对代码进行多处理,尽管这种方法很有效,但是每次插入都会变得越来越慢-50,000个文件花费20分钟,而250,000个文件花费5小时。

我不确定两件事:

  1. 为什么随着数据库中文数量增加插入变得如此慢,我该如何解决呢?我猜这是因为您拥有的记录越多,Mongo需要做更多的工作来检查它试图插入的记录是否已经存在,但是我不确定如何缓解这种情况。
  2. 解决此类问题的最佳方法是什么?我的另一个想法是在本地写入经过处理的图像文件之后进行批量插入。

下面的代码示例:

def process_image(img_file):
   # define MongoClient and collections
   client = MongoClient(...)
   collection = client['collection_name']

   # read image file from s3
   obj = s3.Object(bucket_name='test_bucket',key=img_file)
   im = Image.open(obj.get()['Body'].read()
   
   # create image buffer
   buffer = cv2.imencode(".jpg",im)
   buffer = buffer.flatten().tobytes() # usually around 100,000 bytes

   # dict to be written to mongo
   d = {}
   d['filename'] = img_file
   d['buffer'] = buffer
   
   # insert to mongo
   collection.insert_one(d)

### multiprocessing code

from multiprocessing import Pool

pool = Pool(processes=16)
results = pool.map(process_image,ls_filenames,chunksize=500)
pool.close()
pool.join()

ls_filenames中大约有80万条图像路径。

解决方法

每次创建MongoClient都没有不必要的开销。一次创建一次,然后重新使用连接。