【发布时间】:2013-03-03 13:37:27
【问题描述】:
我需要对需要在数组中旋转一些值的文档执行更新操作。 MongoDB 更新查询当前不允许您在更新中对同一字段使用 $pop 和 $push。在网上搜索了一些建议后,我认为db.eval() 最适合我的使用,因为它可以确保原子性并且我正在执行的操作非常短,因此不会锁定数据库太久。
这是我正在尝试做的事情的一个例子:
db.eval(function (id, newVal) {
doc = db.collection.findOne({_id: id});
doc.values.shift();
doc.values.push(newVal);
db.collection.save(doc);
}, id, newVal);
这非常有效!然后我启用了 mongoDB 分析以查看 eval() 命令占用了多少毫秒,我总是会得到少于 1 毫秒的结果:
> db.system.profile.find({op: "command"}, {"millis": 1})
{ "millis" : 0 }
{ "millis" : 0 }
...
这对我来说是个好消息,除了我的应用程序是在 python 中,所以我使用 pymongo 客户端来执行eval() 命令。 (上面的数据来自 mongo shell)但是现在,当我使用 pymongo 运行相同的eval() 命令时:
conn = pymongo.Connection(mongo_server_hostname)
db = conn.my_db
db.eval("""function (id, newVal) {
doc = db.collection.findOne({_id: id});
doc.values.shift();
doc.values.push(newVal);
db.collection.save(doc);
}""", id, new_val)
我得到了非常不同的分析结果:
> db.system.profile.find({op: "command"}, {"millis": 1})
{ "millis" : 13 }
{ "millis" : 14 }
{ "millis" : 14 }
...
在 mongo shell 和 pymongo 中运行相同的 eval() 命令是否存在根本不同,导致服务器从 pymongo 运行相同的命令要多花 14 毫秒?
【问题讨论】:
-
你能展示你的python代码吗?你是如何从 pymongo 调用 eval 的?它是否采用与 shell 相同类型的
eval锁? -
编辑了问题。我假设 pymongo 的 eval() 导致相同的 eval 命令。我遇到的任何事情都没有让我相信。
-
您的 MongoDB 和 PyMongo 版本是什么?答案可以在 writeconcern 设置中...
-
顺便说一句,我正在分析来自 PyMongo 的 Database Class。
db.eval调用db.command,它的默认参数是check=True。根据文件:'check' (optional): check the response for errors, raising :class:'~pymongo.errors.OperationFailure' if there are any。也许延迟是由检查程序引起的。 -
2.4 版增加了对 Capped Arrays 的支持 - 不使用 db.eval 会解决您的问题吗? docs.mongodb.org/manual/reference/operator/slice/#op._S_slice
标签: performance mongodb profiling eval pymongo