Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecords select(:id).collect vs. pluck(:id) methods: Why is pure AR "pluck" slower?

I am trying to get all the ids from my Article model. I can do it two ways:

 Article.select(:id).collect{|a| a.id}
  Article Load (2.6ms)  SELECT "articles"."id" FROM "articles" 

OR

2.2.1 :006 > Article.pluck(:id)
   (4.3ms)  SELECT "articles"."id" FROM "articles"

What gives? Why is the AR slower than the Ruby version?

Even when I benchmark the Ruby method, it seems faster:

Benchmark.measure{Article.select(:id).collect{|a| a.id}}
  Article Load (1.9ms)  SELECT "articles"."id" FROM "articles"
 => #<Benchmark::Tms:0x007feb12060658 @label="", @real=0.026455502957105637, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.020000000000000018, @total=0.020000000000000018>
like image 486
Jwan622 Avatar asked Sep 02 '15 11:09

Jwan622


People also ask

What does pluck do in Rails?

Rails has a great, expressive term called pluck that allows you to grab a subset of data from a record. You can use this on ActiveRecord models to return one (or a few) columns. But you can also use the same method on regular old Enumerables to pull out all values that respond to a given key.

What is include in Rails?

Rails provides an ActiveRecord method called :includes which loads associated records in advance and limits the number of SQL queries made to the database. This technique is known as "eager loading" and in many cases will improve performance by a significant amount.


2 Answers

Your benchmark is inaccurate. First of all, as you can see, both executions on the database side triggers the same query

SELECT "articles"."id" FROM "articles"

Therefore, the database time should be considered irrelevant. Clearly the two queries had different execution time as shown by the console, but this is normal as if you run the same query 100 times the execution time can be different each time as it depends by a variety of variables such as the machine load, the database state, etc.

Since the database execution time can be considered equivalent, it's irrelevant for the benchmark.

Therefore, what you need to compare is the Ruby execution time and allocation. Pluck is supposed to be faster and more lightweight as compared to collect it doesn't allocate ActiveRecord objects, rather it returns only the selected values.

If you really want to benchmark the methods, you should mock the database time (which is clearly variable but irrelevant for this benchmark) and only benchmark allocation and the two different Ruby methods.

Long story short, pluck is generally more efficient.

like image 156
Simone Carletti Avatar answered Nov 07 '22 14:11

Simone Carletti


select is used to fetch records with specific attributes. It returns an ActiveRecord::Relation object.

pluck can be used the same way select is used, however it returns an array of selected attributes.

You can go through this article.

like image 21
Pravesh Khatri Avatar answered Nov 07 '22 13:11

Pravesh Khatri