我使用 mongodb 来存储压缩的 html 文件。基本上,一个完整的 mongod 文档是这样的:
{'_id': 1, 'p1': data, 'p2': data2, 'p3': data3}
其中数据,数据1,数据3是:bson.binary.Binary(zlib_compressed_html)
我有 1200 万个 id,dataX 每个平均 90KB,所以每个文档至少有 size 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 更新文档。但是,如果 mongo 站点是这种情况,因为我正在向文档添加一个密钥,它不适合并且应该重新排列文档。
可以在集合末尾移动文档,这可能在磁盘上很远。这能减慢速度吗?
还是速度变慢与集合的大小有关?
无论如何,您认为将我的结构修改为如下方式应该更有效:
{'_id': ObjectId, 'mid': 1, 'p': 1, 'd': html}
其中mid=my_id, p=page, d=compressed 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),但是文档将是 3x mores,我将有 2 个索引( _id 和 mid )。
你有什么建议?