【问题标题】:MongoDB performance of db.eval() in javascript shell vs. pymongojavascript shell 与 pymongo 中 db.eval() 的 MongoDB 性能
【发布时间】: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 Classdb.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


【解决方案1】:

您看到的差异的一个可能原因(但不一定是原因)是mongo shell 和mongod 服务器use Google's v8 Javascript engine 默认情况下(尽管它可以配置为使用 Spidermonkey 作为替代)来解释您给出的命令。

Google 的 v8 会在 Javascript 代码中看到热点,并且可能会 JIT 代码经常使用。

另一方面,普通的 PyMongo 是 written in pure Python,这意味着它总是会被解释,这是一个相当大的开销。

如果您还没有这样做,一种可能性是使用 PyMongo extension written in C 而不是默认的,或者,如果您的应用程序的其余部分兼容,则使用 Python 的 PyPy JIT 解释器。

如果您使用从 Debian 派生的任何发行版(如 Ubuntu),则包 python-pymongo-ext 为您提供 PyMongo C 版本的预编译版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    相关资源
    最近更新 更多