Ruby on rails 提高性能,用Rails加载3000条记录?

Ruby on rails 提高性能,用Rails加载3000条记录?,ruby-on-rails,ruby,mongodb,postgresql,heroku,Ruby On Rails,Ruby,Mongodb,Postgresql,Heroku,我有一个在Heroku上运行的Rails应用程序。 我有一条通向“主”控制器和“列表”操作的路线: Rails.application.routes.draw do get 'listings', to: 'home#listings' end 我的上市行动: class HomeController < ApplicationController def listings render json: MultiJson.dump({listings:Listi

我有一个在Heroku上运行的Rails应用程序。 我有一条通向“主”控制器和“列表”操作的路线:

Rails.application.routes.draw do
   get 'listings', to: 'home#listings'

end
我的上市行动:

class HomeController < ApplicationController
    def listings
      render json: MultiJson.dump({listings:Listing.all})
    end

    ...
end
当运行“heroku日志”时,我看到:

Started GET "/listings.json" for 108.6.235.199 at 2015-07-06 14:08:02 +0000
Processing by HomeController#listings as JSON
  Parameters: {"home"=>{}}
  Listing Load (34.3ms)  SELECT "listings".* FROM "listings"
Completed 200 OK in 3717ms (Views: 0.3ms | ActiveRecord: 40.4ms)

通过json加载和呈现3000条记录需要3.7秒是正常的吗?有没有办法将性能提高到100毫秒的量级?为什么ActiveRecord的时间是40.3毫秒,Views是0.3毫秒,而Completed是3717毫秒?使用MongoDB而不是Postgres来快速存储和加载记录是否更好?

问题不是从数据库中获取记录,正如您的日志所示,它在AR进程中只花费40毫秒(3000条记录对PG来说不算什么)。问题是序列化3k条记录


我建议使用帮助优化流程。

问题不是从数据库中获取记录,正如您的日志所示,AR流程只需花费40毫秒(3000条记录对PG来说不算什么)。问题是序列化3k条记录


我建议使用来帮助优化流程。

我跟进了@tagCincy的帖子,了解到构建数据库表中所有记录的json的最快方法是让数据库(在本例中是Postgres)完成所有繁重的工作,让Rails和活动记录休息一下。Postgress支持一种称为“row\u to\u json”的方法

 render json: MultiJson.dump({listings:ActiveRecord::Base.connection.execute("select row_to_json(listings) from listings;")})
这将使性能从3717ms提高6倍 到644ms,如上面和下面的问题所示。实际上甚至比这更好,因为在本例中,我正在提取列表和用户表,而在问题中,我只提取列表表

 >   Started GET "/listings.json?data=(%0A%20%20%20%20settings,%0A%20%20%20%20listings,%0A%20%20%20%20users%0A)" for 108.6.235.199 at 2015-07-07 05:39:15 +0000
 >   (31.5ms)  select row_to_json(users) from users;
 >     Processing by HomeController#listings as JSON
 >       Parameters: {"data"=>"(\n    settings,\n    listings,\n    users\n)", "home"=>{}}
 >        (121.9ms)  select row_to_json(listings) from listings;
 >     Completed 200 OK in 644ms (Views: 0.3ms | ActiveRecord: 153.3ms)

我跟进了@tagCincy的帖子,了解到构建数据库表中所有记录的json的最快方法是让数据库(在本例中是Postgres)完成所有繁重的工作,让Rails和活动记录休息一下。Postgress支持一种称为“row_to_json”的方法

 render json: MultiJson.dump({listings:ActiveRecord::Base.connection.execute("select row_to_json(listings) from listings;")})
这将使性能从3717ms提高6倍 到644ms,如上面和下面的问题所示。实际上甚至比这更好,因为在本例中,我正在提取列表和用户表,而在问题中,我只提取列表表

 >   Started GET "/listings.json?data=(%0A%20%20%20%20settings,%0A%20%20%20%20listings,%0A%20%20%20%20users%0A)" for 108.6.235.199 at 2015-07-07 05:39:15 +0000
 >   (31.5ms)  select row_to_json(users) from users;
 >     Processing by HomeController#listings as JSON
 >       Parameters: {"data"=>"(\n    settings,\n    listings,\n    users\n)", "home"=>{}}
 >        (121.9ms)  select row_to_json(listings) from listings;
 >     Completed 200 OK in 644ms (Views: 0.3ms | ActiveRecord: 153.3ms)


您应该首先找出哪一层增加了开销。在SQL客户机中运行
explain analyze select*from listings
时会发生什么?为此报告的运行时是什么?它在服务器端测量查询的运行时,不包括任何网络或前端开销。请尝试将这些3k记录硬编码到数据库中的数组中你的控制器,看看它需要多少时间来渲染。这不是数据库性能的问题。3k对象需要时间来渲染。我建议你开始在服务器端使用某种分页。你为什么要一次发送那么多数据到客户端?@xlembouras,我喜欢你的建议,所以我加入了一个虚拟3000个哈希数组,我收到了这样的消息:“在929ms内完成了200个OK(视图:0.2ms | ActiveRecord:0.0ms)”,这几乎少了3秒-所以从数据库中获取肯定会占用大量时间。据我所知,您可以使用任何SQL客户机(例如
psql
)连接到Heroku数据库-但我从未使用过Heroku,所以我不知道它到底是如何工作的。您应该首先找出哪一层增加了开销。在SQL客户端中运行
explain analyze select*from listings
时会发生什么?为此报告的运行时是什么?它测量服务器上查询的运行时ide,不包括任何网络或前端开销。尝试将这些3k记录硬编码到控制器中的数组中,并查看渲染所需的时间。这不是数据库性能的问题。3k对象需要时间渲染。我建议您开始在服务器端使用某种分页。您为什么要使用这种方式不管怎样,一次就把那么多数据发送到客户端?@xlembouras,我喜欢你的建议,所以我放入了一个3000个散列的虚拟数组,我收到了这样的消息:“在929ms内完成了200个OK(视图:0.2ms | ActiveRecord:0.0ms)”,这几乎少了3秒,所以从数据库中提取肯定会占用很多时间。据我所知,你可以使用任何SQL客户端(例如,
psql
)连接到Heroku数据库-但我从未使用过Heroku,所以我不知道它到底是如何工作的。我也这么认为-所以我放入了一个包含3000个散列的虚拟数组,我收到了这样的消息:“在929ms内完成了200个OK(视图:0.2ms;活动记录:0.0ms)'这几乎少了3秒-因此从数据库获取肯定会占用大量时间。进行SQL调用只需40毫秒,但在运行时加载所有对象仍需3秒。是的,MultiJSON可以序列化哈希数组,比ActiveRecord\u关系对象快得多。查看日志:
Listing load(34.3毫秒)选择“listings”“*FROM”listings“
从数据库检索记录只需34.4ms,从其他4.1ms将集合返回控制器。如果进入Rails控制台,您可以看到瓶颈:检索列表并设置为局部变量,然后运行
Benchmark.measure{MultiJson.dump(清单:)}
谢谢tagCincy,我这样做了,但是没有显示任何内容:2.2.1:004?>listings=Listing.all 2.2.1:005>listings.count(6.8ms)从“listings”=>3005 2.2.1:006>Benchmark.measure{MultiJson.dump(Listing:listings}中选择count(*)2.2.1:007?>那么瓶颈是什么呢?Benchmark.measure显示了大量的输出,但不是那个特定的命令,也许我们可以继续聊天,我可以告诉你我也这么认为-所以我放入了一个3000个散列的虚拟数组,我收到了这样的消息:“在929ms内完成了200个OK(视图:0.2ms |活动记录:0.0ms)'这几乎少了3秒-因此从数据库获取肯定会占用大量时间。进行SQL调用只需40毫秒,但在运行时加载所有对象仍需3秒。是的,MultiJSON可以序列化