performance
select
, pluck
select
, pluck
pluck
will load an array of column, and is faster than select
.
select
is ~10X slower than pluck
, because of creating objects.
User.select(:id).to_a
# => User Load (0.9ms) SELECT id FROM "users"
# => [#<User id: 12>, #<User id: 42>, #<User id: 1>, #<User id: 24>, #<User id: 200>, ...]
User.pluck(:id)
# => (0.9ms) SELECT "users"."id" FROM "users"
# => [12, 42, 1, 24, 200, ..., 365]
User.pluck(:first_name, :last_name, :email)
# => (2.2ms) SELECT "users"."first_name", "users"."last_name", "users"."email" FROM "users"
# => [[nil, nil, "jeff@gmail.com"], ['joe', nil, "joe.brown@gmail.com"], ["Edward", "Stanza", "ed@email.com"], ...]
http://gavinmiller.io/2013/getting-to-know-pluck-and-select/
How long to build ActiveRecord models
10.4ms for db query, but total 143ms for the whole process.
User.all.to_a
# => User Load (10.4ms) SELECT "users".* FROM "users"
# => [#<User id: 263, ... >, #<User id: 264, ... >, #<User id: 265, ... >, ... ]
puts Benchmark.measure { User.all.to_a }
user system total real
0.143333 0.000000 0.143333 ( 0.163123)
Preload, Eagerload, Includes and Joins
preload
, eager_load
, includes
= eager loading (prevent n+1)
Preload
loads the association data in a separate query.User.preload(:posts).to_a # => SELECT "users".* FROM "users" SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1)
Since
preload
always generates two sql, we can’t use posts table in where condition.User.preload(:posts).where("posts.desc='ruby is awesome'") # => SQLite3::SQLException: no such column: posts.desc:
eager_loading
loads all association in a single query using LEFT OUTER JOIN.User.eager_load(:posts).to_a # => SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0, "posts"."title" AS t1_r1, "posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3 FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
Includes
Behaves based on situations, intelligent!
Blog.includes(:posts) # => Blog Load (2.8ms) SELECT "blogs".* FROM "blogs" Post Load (0.7ms) SELECT "posts".* FROM "posts" WHERE "posts"."blog_id" IN (1, 2, 3) Blog.includes(:posts).where(name: 'Blog 1').where(posts: {title: 'Post 1-1'}) # => SQL (0.2ms) SELECT "blogs"."id" AS t0_r0, "blogs"."name" AS t0_r1, "blogs"."author" AS t0_r2, "blogs"."created_at" AS t0_r3, "blogs"."updated_at" AS t0_r4, "posts"."id" AS t1_r0, "posts"."title" AS t1_r1, "posts"."created_at" AS t1_r2, "posts"."updated_at" AS t1_r3, "posts"."blog_id" AS t1_r4 FROM "blogs" LEFT OUTER JOIN "posts" ON "posts"."blog_id" = "blogs"."id" WHERE "blogs"."name" = ? AND "posts"."title" = ? [["name", "Blog 1"], ["title", "Post 1-1"]]
includes
+references
=eager_loading
Joins
brings association data using inner join.User.joins(:posts) # => SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
Intention for eager loading
# Give me users with polish addresses and preload only polish addresses
User.includes(:addresses).where("addresses.country = ?", "Poland")
# Give me users with polish addresses and preload only polish addresses(same, but inner join)
User.joins(:addresses).where("addresses.country = ?", "Poland").includes(:addresses)
# Give me users with polish addresses but preload all of their addresses.
User.joins(:addresses).where("addresses.country = ?", "Poland").preload(:addresses)
Too much query
Array
DB query
sort_by
order
.select { c c.label != 'All' }
.where.not(label: 'All')
http://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html
Last updated
Was this helpful?