如何提高我的特定Ruby on Rails应用程序运行时性能

时间:2014-01-20 12:27:34

标签: ruby-on-rails performance

我最近加入了Ruby on Rails项目,其目标是改善一些运行时性能,因为有些请求需要花费太多秒(20+),我们希望减少它。对于长篇文章我很抱歉,但我正在寻求如何解决这么复杂问题的建议。

我首先要说的是,由于大多数这些请求后面都会有用户输入,因此将其移至后台任务将无助于问题的本质,因为用户仍需等待响应。另外我要补充一点,在这个时候我不能广泛地改变模型架构,只是可以增强它。

说,快速概述相关模型:

  • 有一个根类,有许多其他类,还有许多其他类等。
  • 此层次结构中有许多级别(深度约为7-10级)。
  • 这些类中有相当多的“范围”,用于通过某些参数过滤关联,例如:所有状态为“有效”的人

例如:

    class A < ActiveRecord::Base
      has_many :bs, :inverse_of => a
      has_many :cs, :inverse_of => a
    end

    class B < ActiveRecord::Base
      belongs_to :a, :inverse_of => bs
      has_many :ds, :inverse_of => b

      scope :by_active_status, lambda { where(:status => ‘active’) }
    end

    class C < ActiveRecord::Base
      belongs_to :a, :inverse_of => cs
      has_many :es, :inverse_of => c
    end

    class D < ActiveRecord::Base
      belongs_to :b, :inverse_of => ds
      ...and so on
    end

    class E < ActiveRecord::Base
      belongs_to :c, :inverse_of => es
      ...and so on
    end

作为一个例子,我们有一些比较实用程序,它比较了所有级别的2个根对象。这不是浅层比较,有些领域具有比较意义,有些领域没有,例如,如果一个对象有一个名称,描述&amp;价格与价格无关,因此,即使只有名称和价格,也认为2个对象是相等的。描述匹配。请注意,比较方法在内部使用上述范围。

现在性能不好主要是因为每个对象都是由DB(MySql)自己加载的,这意味着有很多数据库查询。我的第一件事是对整个层次结构使用eager-load('includes'),但是由于使用这些范围它没有帮助。

例如:A.where(:id => some_id).includes([{:b => d}, {:c => e}])

但是在比较A的方法中,它只需要比较活动的子B,因此它使用范围'by_active_status',从而执行另一个数据库查询(在哪里)另外,Ds及其关联不加载等。)。

我找到了类似这些示例的代码:a.bs.by_active_statusc.bs.by_active_status

我发现自己更改了使用这些范围的地方,在已经加载关联的情况下,它将从已加载对象的数组中选择相关对象,以及在何处应该使用关联(其他代码流到那里)。它有助于短期,但这看起来非常难看,而不是红宝石式。

我必须承认,最初让我感到惊讶的是,这些“无辜”的范围隐藏着这样的性能问题。 那就是目前的情况。

有关此问题的方法的任何建议吗?

=== EDITED ===

根据要求,这是一个等效的示例schema.rb:

create_table "as", :force => true do |t|
  t.string   "some_string"
  t.integer  "some_int"
end

create_table "bs", :force => true do |t|
  t.integer  "a_id",                   :null => false
  t.string   "some_string"
  t.integer  "some_int"
end
add_index "bs", ["a_id"], :name => "index_bs_on_a_id"

create_table "cs", :force => true do |t|
  t.integer  "a_id",                   :null => false
  t.string   "some_string"
  t.integer  "some_int"
end
add_index "cs", ["a_id"], :name => "index_cs_on_a_id"

create_table "ds", :force => true do |t|
  t.integer  "b_id",                   :null => false
  t.string   "some_string"
  t.integer  "some_int"
end
add_index “ds", [“b_id"], :name => "index_ds_on_b_id"

create_table “es", :force => true do |t|
  t.integer  “c_id",                   :null => false
  t.string   “some_string"
  t.integer  “some”_int
end
add_index “es", [“c_id"], :name => "index_es_on_c_id"

0 个答案:

没有答案