Ashbury
Ashbury

Reputation: 2346

Rails benchmark reports less time than activerecord query

I'm trying to benchmark this query:

Person.where(age: 60)

When I run it in the console it says:

Person Load (1.2ms) SELECT "people".* FROM "people" WHERE "people"."age" = ? [["age", 60]]

When I benchmark it, it reports 0.17ms

def self.get_ages_sql
  sixties = Person.where(age: 60)
end

Benchmark.bmbm do |x|
x.report('sql') {Person.get_ages_sql}
end

Whats the discrepency between: 0.17ms (benchmark) vs 1.2ms (reported when I run command in console)

Upvotes: 1

Views: 527

Answers (1)

Pavel Mikhailyuk
Pavel Mikhailyuk

Reputation: 2877

This code does not do database request actually:

Person.where(age: 60)

It just build ActiveRecord::Relation. You can ensure by executing next code line by line in console and watch wich line actually produce DB request:

relation = Person.where(age: 60); 1
relation.class.name
relation.to_a

But Console misleads you with "Person Load ..." because it calls additional method like #inspect on each code line result. And this additional method causes DB request:

relation = Person.where(age: 60).inspect; 1

And that is why your benchmark is wrong - you do test of query creation not whole DB request. It should look like:

def self.get_ages_sql
  Person.where(age: 60).to_a
end

Added: To get deep into Console, create

class ConsoleTest
  def inspect
    data.inspect
  end

  def data
    'Doing DB request'
  end

  def self.test_data
    ct = self.new
    puts 'No request yet'
    ct.data
  end
end

and then try in Console:

ct = ConsoleTest.new

and

ct = ConsoleTest.new; 1
ct.data

and

ConsoleTest.test_data

Upvotes: 2

Related Questions