在生产环境中,Rails + Mongoid查询速度慢

3
我在使用Mongoid查询时遇到了性能问题,尤其是在生产环境中。 我最初认为这与主机有关(使用的是最小的Linode实例),但当我迁移到更大的实例后,查询速度略有改善。 以产品页面为例,在生产环境中加载需要大约800毫秒至1000毫秒的时间(在开发环境中为60毫秒),但在主机迁移后,它在生产环境中的速度大约在300毫秒至800毫秒之间。 这让我相信缓慢是由于低效的查询以及可能存在的n+1副作用引起的。 下面是我访问产品API时发生的情况快照:
MOPED: 173.255.252.208:27017 QUERY database=* collection=orders selector=    {"$query"=>{"user_id"=>"52cc529eec5cb38bbf000001"}, "$orderby"=>{:_id=>1}} flags=[] limit=-1   skip=0 batch_size=nil fields=nil (20.6976ms)
MOPED: 173.255.252.208:27017 QUERY database=* collection=orders selector={"$query"=>{"user_id"=>"52cc529eec5cb38bbf000001"}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil (13.5436ms)
MOPED: 173.255.252.208:27017 COMMAND      database=* command={:count=>"orders", :query=>{"user_id"=>"52cc529eec5cb38bbf000001"}} (18.1813ms)
MOPED: 173.255.252.208:27017 QUERY        database=* collection=orders selector={"$query"=>{"user_id"=>"52cc529eec5cb38bbf000001"}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil (15.9233ms)
MOPED: 173.255.252.208:27017 QUERY        database=* collection=orders selector={"$query"=>{"user_id"=>"52cc529eec5cb38bbf000001"}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil (29.9242ms)
MOPED: 173.255.252.208:27017 QUERY        database=* collection=orders selector={"$query"=>{"user_id"=>"52cc529eec5cb38bbf000001"}, "$orderby"=>{:_id=>1}} flags=[] limit=0 skip=0 batch_size=nil fields=nil (69.3288ms)

看起来这是导致缓慢的主要原因,但是为什么查询订单集合会如此缓慢?下面是Mongodb的stats():

db.orders.stats()
{
    "ns" : "orders",
    "count" : 21535,
    "size" : 15068736,
    "avgObjSize" : 699.7323426979336,
    "storageSize" : 23617536,
    "numExtents" : 7,
    "nindexes" : 3,
    "lastExtentSize" : 9555968,
    "paddingFactor" : 1.025000000000004,
    "systemFlags" : 1,
    "userFlags" : 0,
    "totalIndexSize" : 5567856,
    "indexSizes" : {
        "_id_" : 711312,
        "order_number_index" : 972944,
        "_keywords_1" : 3883600
    },
    "ok" : 1
}

这个集合本身似乎相当小(22k条记录),所以查询为什么会如此缓慢令人困惑。正如您所看到的,我在集合上添加了索引,因此我不知道该如何提高查询速度。非常感谢您的帮助!谢谢!


你使用的Mongo版本是什么? - cenouro
1个回答

0

由于您正在按user_id查询订单,因此在user_id上添加索引可能是一个好主意。索引{ user_id: 1 }应该没问题。

如果您在应用程序中发布了相关代码,则更容易确定它是否为n+1查询。但是,看起来可能是这样,因为您多次查询订单集合;更有效的查询将选择其中用户ID在用户ID数组中的订单。请参见{{link1:here}}以获取有关mongoid文档中贪婪加载的信息。基本上,如果您使用类似于User.all.each { |u| puts u.orders }的方式迭代用户订单,那么只需在.each之前添加.includes(:orders)即可使其更加高效。

如果您仍然遇到速度问题,可能值得在控制台上获取查询数据库的代码行并对其运行.explain。请参阅此处以了解如何理解结果,或者如果您使用的是2.6而不是3.0,则参阅此处。最重要的是查看正在扫描的文档数与输出中匹配条件的文档数之间的差异。例如,如果您有21535个文档且没有user_id索引,则每次查找匹配该user_id的文档时都可能扫描所有21535个文档。添加索引后,.explain将在计划部分下显示是否使用索引。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接