我使用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)。
你有什么建议?
答案 0 :(得分:0)
如果您继续将html页面添加为新属性,则文档重定位可能会成为问题。将页面移动到新集合是否真的是一个问题,您可以在其中添加一个记录?另外我并不认为MongoDB非常适合您的用例。例如。 Redis会更有效率。 您需要注意的另一件事是{_ 3}}为您的_id索引。使用db.mongocol.stats()检查索引大小。
答案 1 :(得分:0)
将新文档插入MongoDB时,文档可以增长而不会将其移动到某个点。因为DB正在分析传入的数据并向文档添加填充。 因此,处理较少的文档动作可以做两件事:
手动调整填充因子
为每个文档预分配空间(属性)。
有关填充因子的详细信息,请参阅Article about Padding或MongoDB Docs。
顺便说一下。如果_id已经存在(.save()将覆盖你的文档),你应该使用.insert()来设置一个重复的键错误。