【问题标题】:Slow MongoDB/pymongo query缓慢的 MongoDB/pymongo 查询
【发布时间】:2015-01-29 02:31:31
【问题描述】:

我正在使用 python 的 pymongo 库向 MongoDB(2.6 版)提交一个非常简单的查询:

query = {"type": "prime"}
logging.info("Querying the DB")
docs = usaspending.get_records_from_db(query)
logging.info("Done querying. Sorting the results")
docs.sort("timestamp", pymongo.ASCENDING)
logging.info("Done sorting the results, getting count")
count = docs.count(True)
logging.info("Done counting: %s records", count)
pprint(docs[0])
raise Exception("End the script right here")

get_records_from_db() 函数非常简单:

def get_records_from_db(query=None):
    return db.raws.find(query, batch_size=50)

请注意,我实际上需要处理所有文档,而不仅仅是docs[0]。我只是想以docs[0] 为例。

当我运行这个查询时,我得到的输出是:

2015-01-28 10:11:05,945 Querying the DB
2015-01-28 10:11:05,946 Done querying. Sorting the results
2015-01-28 10:11:05,946 Done sorting the results, getting count
2015-01-28 10:11:06,617 Done counting: 559952 records

但是我再也回不来docs[0]。我在{"timestamp": 1}{"type": 1} 上有一个索引,查询似乎工作得相当好(因为返回的计数非常快),但我不确定为什么我永远不会取回实际文档(文档很小[ 50K以下])。

【问题讨论】:

  • 是不是因为你有一些超高的日志记录设置?
  • 不确定 pymongo 中的日志记录会如何影响性能,但日志记录设置为 logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)

标签: python mongodb pymongo


【解决方案1】:

当您执行这些行时,PyMongo 在服务器上没有实际工作:

query = {"type": "prime"}
docs = usaspending.get_records_from_db(query)
docs.sort("timestamp", pymongo.ASCENDING)

此时“docs”只是一个 PyMongo 游标,但它没有在服务器上执行查询。如果在 Cursor 上运行“count”,那么 PyMongo 会在服务器上执行“count”命令并返回结果,但 Cursor 本身仍未执行。

但是,当你运行这个时:

docs[0]

然后为了得到第一个结果,PyMongo 在服务器上运行查询。查询是按“类型”过滤并按“时间戳”排序的,所以在 mongo shell 上试​​试这个,看看查询有什么问题:

> db.collection.find({type: "prime"}).sort({timestamp: 1}).limit(1).explain()

如果您看到一个非常大的“nscanned”或“nscannedObjects”,那就是问题所在。您可能需要类型和时间戳的复合索引(顺序很重要):

> db.collection.createIndex({type: 1, timestamp: 1})

my article on compound indexes

【讨论】:

  • 该查询本身需要很长时间才能完成:-)
  • 哪个查询? “解释”时间过长?
  • 在这种情况下尝试创建索引。
  • 是的。创建索引解决了这个问题。我想知道为什么性能这么慢?也许正在执行集合扫描。我会将此标记为答案。
  • 谢谢!它很慢,因为您现有的索引 {"timestamp": 1} 和 {"type": 1} 对您的查询不是很有效。 MongoDB 选择了其中的 一个 来使用,但是它要么必须使用“类型”索引并对“时间戳”进行内存排序,要么必须使用“时间戳”索引排序并跳过许多类型错误的记录。复合索引非常有效地为您提供答案。
【解决方案2】:

您永远无法取回实际文档的原因是因为 Mongo 将这些命令集中到一个查询中,所以您会这样看:

find 记录然后sort 记录然后count 记录。

您需要构建两个完全独立的查询:

  1. find记录,sort记录,然后给我记录
  2. count记录

如果你把它们锁起来,Mongo 会锁住它们并认为它们是一个命令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-17
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 2017-09-08
    • 1970-01-01
    • 2012-12-24
    相关资源
    最近更新 更多