Rails的性能与ActiveRecord的关系

时间:2015-03-27 14:36:23

标签: ruby-on-rails performance ruby-on-rails-4 activerecord database-performance

当我只需要一个或两个字段时,我一直默认使用pluck,但我最近对性能差异进行了基准测试,并且丢失了:

ActiveRecord::Base.logger.level = 1
n = 5000
Benchmark.bm do |x|
  x.report('Country.all:              ') { n.times { Country.all } }
  x.report('Country.unscoped:         ') { n.times { Country.unscoped } }
  x.report('base priority_order:      ') { n.times { Country.unscoped.with_translations(I18n.locale).order(list_at_top:   :desc).order(:name) } }
  x.report('.includes(:translations): ') { n.times { Country.unscoped.with_translations(I18n.locale).order(list_at_top: :desc).order(:name).includes(:translations) } }
  x.report('.pluck(:name):            ') { n.times { Country.unscoped.with_translations(I18n.locale).order(list_at_top: :desc).order(:name).includes(:translations).pluck(:name) } }
  x.report('.pluck(:name) only:       ') { n.times { Country.unscoped.with_translations(I18n.locale).order(list_at_top: :desc).order(:name).pluck(:name) } }
end

# Results
=begin
                                  user     system      total        real
  Country.all:                0.990000   0.020000   1.010000 (  1.023518)
  Country.unscoped:           0.050000   0.000000   0.050000 (  0.050440)
  base priority_order:        1.350000   0.010000   1.360000 (  1.356728)
  .includes(:translations):   1.460000   0.000000   1.460000 (  1.462635)
  .pluck(:name):              8.230000   0.150000   8.380000 ( 11.168291)
  .pluck(:name) only:         6.980000   0.150000   7.130000 (  9.903130) 
=end

正如你所看到的,采摘的实时时间要慢得多。我选择了第4个.includes(:translations)以避免N + 1个查询(前两个实际上只是基线,没有提供所需的数据)。

这个基准测试是否准确,采摘真的更慢,还是这不能说明整个故事?由于没有创建ActiveRecord对象,因此应该节省大量内存,并节省一些时间。

1 个答案:

答案 0 :(得分:3)

您的测试不准确。 Country.all实际上并未获取行,它只会返回活动记录关系。与您的其他范围相同。只有pluck才会实际查询数据。

我有一个包含243行的国家/地区表。列数不多(id,name,iso2,iso3)。我将你的查询调整到map(&:name)前两个,所以结果与采摘相同。 Pluck赢了很多。

  ActiveRecord::Base.logger.level = 1
  n = 1000
  Benchmark.bm do |x|
    x.report('Country.all.map(&:name):      ') { n.times { Country.all.map(&:name) } }
    x.report('Country.unscoped.map(&:name): ') { n.times { Country.unscoped.map(&:name) } }
    x.report('Coutry.pluck(:name):          ') { n.times { Country.unscoped.pluck(:name) } }
  end

输出:

                                    user     system      total        real
Country.all.map(&:name):        3.830000   0.140000   3.970000 (  4.328655)
Country.unscoped.map(&:name):   3.780000   0.030000   3.810000 (  4.159162)
Coutry.pluck(:name):            1.550000   0.040000   1.590000 (  1.879490)