Bypassing ActiveRecord query cache
ActiveRecord by default caches queries for performance. You might see something like the following the logs:
User Load (84.6ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
The first sql query actually executes against the db and is cached for the subsequent 4 calls so you only incur one db hit. However sometimes this may not be the results you want. In the example above each time you are expecting a different random user however because the query results were cached you will keep getting the same user (e.g. Joe), rather than (Joe, Jill, Edward, ...)
To get this right, we need to disable caching for this query and it can be done with the uncached scoping:
uncached do
active.where("badges_count > 1").order("Random()").limit(limit)
end
this will result in the expected 5 individual queries with distinct results:
User Load (84.2ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
User Load (83.0ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
User Load (83.8ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
User Load (83.3ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
User Load (83.2ms) SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND (badges_count > 1) ORDER BY Random() LIMIT 1
Written by Bashir Eghbali
Related protips
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
#Activerecord
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#