问题:我想在给定的一天从 MongoDb 读取大量交易。无论我如何尝试阅读一天的内容,我的阅读总是停滞不前。停顿点始终相同,但可以根据我的批量大小设置进行更改。
系统:Linux-Mint,Python:3.5,MongoDB 3.2,PyMongo
代码:
def write_transactions_to_file(start: datetime, end: datetime, filename: str):
print ("Writing transactions to file")
new_start = start
new_end = new_start + timedelta(hours=1)
with open(filename, 'w') as f:
while new_start < end:
print("Starting hour {}".format(new_start.hour))
query = Builder().find(TimeStamp=Gt(new_start)).And(TimeStamp=Lt(new_end)).query
transactions = find(tx_collection, query)
for c, t in enumerate(transactions):
j = json.dumps(t, default=json_util.default)
f.write("{}\n".format(j))
print("{}:{}".format(c,t))
new_start=new_start+timedelta(hours=1)
new_end = new_start+timedelta(hours=1)
print("Transactions written to file")
def find(self, collection, query):
return collection.find(query).batch_size(25)
“查询”的值 = {'$and': [{'TimeStamp': {'$gt': datetime.datetime(2017, 10, 24, 0, 0)}}, {'TimeStamp': {'$ lt': datetime.datetime(2017, 10, 24, 1, 0)}}]}
试过: 本来,我只是查询了一整天。在停滞之前,这让我获得了大约 16k 条记录。后来我将批量大小更改为 100,这让我在停顿前达到了约 29k 条记录。接下来,我尝试将查询限制为一次一小时。那也总是停滞不前(每次都在同一个地方)。但是,它的停顿点因批量大小而异。
可能是问题的几件事:
如果
Timestamp
字段上的索引不是前缀(请参阅Compound Indexes: Prefix),则查询可能没有有效执行。由于查询严重依赖于 Timestamp
字段,因此建议基于该字段创建单独的索引,或确保该字段出现在任何复合索引中的第一个。您观察到的停顿可能是由于服务器的内存已满,因此它试图从磁盘中获取更多文档。这种等待磁盘访问可能是停顿。您可以使用
iostat
确定是否属于这种情况,并查看停顿期是否对应于高磁盘利用率。如果您的服务器使用的是旋转磁盘而不是 SSD,这通常是一个问题。