MongoDb速度下降

时间:2012-11-30 09:23:13

标签: python mongodb nosql

我使用mongodb来存储压缩的html文件。 基本上,一个完整的mongod文档就像:

{'_id': 1, 'p1': data, 'p2': data2, 'p3': data3}

其中data,data1,data3为:bson.binary.Binary(zlib_compressed_html)

我有12百万个ID,dataX每个平均90KB, 所以每个文档的大小至少为180KB + sizeof(_id) + some_overhead

总数据大小至少为2TB。

我想注意'_id'是索引。

我按照以下方式插入mongo:

def _save(self, mongo_col, my_id, page, html):
    doc = mongo_col.find_one({'_id': my_id})
    key = 'p%d' % page
    success = False
    if doc is None:
        doc = {'_id': my_id, key: html}
        try:
            mongo_col.save(doc, safe=True)
            success = True
        except:
            log.exception('Exception saving to mongodb')
    else:
        try:
            mongo_col.update({'_id': my_id}, {'$set': {key: html}})
            success = True
        except:
            log.exception('Exception updating  mongodb')
    return success

正如您所看到的,我首先查找集合以查看文档是否包含 my_id存在。

如果它不存在,那么我创建它并将其保存到mongo其他我更新它。

上面的问题是虽然它速度非常快,但在某些时候它变得非常慢。

我会给你一些数字:

当它很快时,我每4小时做1.500.000,每4小时做300.000。

我怀疑这会影响速度:

请注意

执行将文档大小增加到超出该文档的已分配空间的更新操作时,更新操作会将文档重定位到磁盘上,并可能根据更新类型对文档字段重新排序。

As of these driver versions, all write operations will issue a getLastError command to confirm the result of the write operation: { getLastError: 1 } Refer to the documentation on write concern in the Write Operations document for more information.

以上内容来自:http://docs.mongodb.org/manual/applications/update/

我说的是因为我们可以拥有以下内容:

{'_id: 1, 'p1': some_data}, ...., {'_id': 10000000, 'p2': some_data2}, ...{'_id': N, 'p1': sd3}

并想象我将上述_save方法称为:

_save(my_collection, 1, 2, bin_compressed_html)

然后它应该用_id 1更新doc。但如果mongo网站是这样的话, 因为我正在为它不适合的文档添加一个键,应该重新排列文档。

可以在集合的末尾移动文档,这可能在磁盘上很远。这会让事情变慢吗?

或者速度减慢与集合的大小有关吗?

以任何方式认为修改我的结构应该更有效:

{'_id': ObjectId, 'mid': 1, 'p': 1, 'd': html}

其中mid = my_id,p = page,d =压缩html

并修改_save方法只进行插入?

def _save(self, mongo_col, my_id, page, html):
    doc = {'mid': my_id, 'p': page, 'd': html}
    success = False
    try:
        mongo_col.save(doc, safe=True)
        success = True
    except:
        log.exception('Exception saving to mongodb')
    return success

这样我就避免了更新(所以在磁盘上重新排列)和一次查找(find_one) 但文件将是3倍以上,我将有2个索引(_id和mid)。

你有什么建议?

2 个答案:

答案 0 :(得分:0)

如果您继续将html页面添加为新属性,则文档重定位可能会成为问题。将页面移动到新集合是否真的是一个问题,您可以在其中添加一个记录?另外我并不认为MongoDB非常适合您的用例。例如。 Redis会更有效率。 您需要注意的另一件事是{_ 3}}为您的_id索引。使用db.mongocol.stats()检查索引大小。

答案 1 :(得分:0)

将新文档插入MongoDB时,文档可以增长而不会将其移动到某个点。因为DB正在分析传入的数据并向文档添加填充。 因此,处理较少的文档动作可以做两件事:

  1. 手动调整填充因子

  2. 为每个文档预分配空间(属性)。

  3. 有关填充因子的详细信息,请参阅Article about PaddingMongoDB Docs

    顺便说一下。如果_id已经存在(.save()将覆盖你的文档),你应该使用.insert()来设置一个重复的键错误。