【问题标题】:Trouble optimizing Rails queries in controller在控制器中优化 Rails 查询时遇到问题
【发布时间】:2013-05-31 00:34:25
【问题描述】:

我似乎无法弄清楚为什么我的总渲染时间与我的活动记录时间 + 我的生产日志中列出的查看时间不匹配。

这是我的生产日志的输出:

在 12508 毫秒内完成 200 次 OK(查看次数:0.3 毫秒 | ActiveRecord:46.0​​ 毫秒)

这是我控制器中的代码:

store = Store.find(:vanity_url => params[:vanity_url])
render :json => store.get_pages_with_includes
return false

在我的 Store.rb 模型中,我使用两种方法来呈现模型的 json 表示及其所有活动关系。这是急切的加载方法:

def eager_load_pages
    pages = Page.where(:store_id => self.id).includes(
        [{:menu_items => 
            [
                :sizes, 
                {:topping_groups => 
                    {:toppings => :sizes}
                }
            ]
        },
        {:combos => 
            {:combo_item_groups => 
                {:combo_items => 
                    [
                        :sizes,
                        {:topping_groups => 
                            {:toppings => :sizes}
                        }
                    ]
                }
            }
        }]
    ).order('position ASC')
    return pages
end

这里是 to_json 方法

def get_pages_with_includes
    pages = self.eager_load_pages
    return pages.to_json({:include =>  
        [{:menu_items => 
            {:include =>
                {:topping_groups =>
                    {:include => 
                        {:toppings => 
                            {:include => 
                                :sizes
                            }
                        }
                    }
                }
            }
        },
        {:combos =>
            {:include =>
                {:combo_item_groups => 
                    {:include => 
                        {:combo_items =>
                            {:include => 
                                [:sizes, :topping_groups => 
                                    {:include => 
                                        {:toppings => 
                                            {:include =>
                                                :sizes
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        }]
    })
end

所有代码都在工作,我不确定是否可以提高效率。我感到困惑的是,为什么总页面加载时间甚至不接近运行查询所需的时间。谁能帮我吗?请??从技术上讲,该页面的加载时间应该少于 50 毫秒,但它需要 12508 毫秒!

任何帮助将不胜感激!

---------更新------------ 我从我的服务器运行 top 并注意到在这些查询期间 ruby​​ 占用了 100% 的 CPU。这里有什么想法吗?也许这指向了问题......?

【问题讨论】:

    标签: ruby-on-rails optimization activerecord


    【解决方案1】:

    很可能在您的控制器中呈现为 JSON 的时间太长了。您要渲染多少条记录? 如果您的 Ruby 进程占用了所有可用的 CPU,这意味着它与您的数据库没有(直接)相关,但可能是以下任何一种:

    • 从您的数据库中实例化对象(如果您要检索 10,000 条记录);
    • 将这些对象呈现为 JSON。

    查看您的页面加载时间(Views: 0.3ms | ActiveRecord: 46.0ms) 我会说这是对 JSON 的呈现。它不会在Views 下显示,因为您没有使用任何视图,而是直接在控制器中调用渲染操作。

    我建议您在您的应用中添加一些工具(例如 New Relic RPM),或者甚至是简单的基准测试方法,以找出需要这么长时间的原因。

    您可能还想考虑使用更快的 JSON 解析器/渲染器,而不是默认的。查看multi_json gem。

    【讨论】:

    • 这个回复信息量很大!谢谢你的澄清!我将检查 multijson gem,因为 json 是当前唯一呈现的其他内容。有没有更好的方法来收集所有活动关系并将它们发送到视图以供 javascript 收集?
    • 数据库检索正常。只是一些不必要的返回语句。请记住,如果您没有明确的返回值,Ruby 方法会返回最后一条语句的值。所以eager_load_pages 不需要变量赋值和返回语句。您可以查看 jbuilder 或类似的 JSON 视图构建器,而不是使用大的 render 调用来构建正确的视图。但它们当然也会带来一点开销。
    • 这是个好建议!调查 jbuilder ,似乎它可能对我有用。对我来说唯一的麻烦是一旦我急切地加载一个对象,我真的需要所有这些数据都是嵌套的密集数组。但即使在急切加载之后,似乎当我尝试构建自己的数组时,它会重新运行查询并导致很大的延迟。这就是为什么我求助于 .to_json 方法。 jbuilder能解决吗?意思是,它与预先加载的模型交互的方式是否允许我不重新运行查询?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 2013-11-25
    • 2019-04-03
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多