May 16, 2018
Prior to Rails 5.2, MySQL and PostgreSQL adapters had select_value
,
select_values
& select_rows
select_{value,values,rows}
methods. They
improve the performance by not instantiating ActiveRecord::Result
.
However these methods broke query caching of
ActiveRecord::FinderMethods#exists?
method. Let's check the issue.
>> User.cache do
>> 2.times { User.exists?(1) }
>> end
User Exists (2.1ms) SELECT 1 AS one FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
User Exists (2ms) SELECT 1 AS one FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
As we can see, query was not cached and sql was executed second time.
From Rails 5.2, MySQL and PostgreSQL adapters are no longer override select_{value,values,rows} methods which fix this query caching issue.
Also, the performance improvement provided by these methods was marginal and not a hotspot in Active Record, so this change was accepted.
Let's check query caching of ActiveRecord::FinderMethods#exists?
after the
change.
>> User.cache do
>> 2.times { User.exists?(1) }
>> end
User Exists (2.1ms) SELECT 1 AS one FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
CACHE User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Now, query has been cached as expected.
This change has been backported in rails 5.1 from version 5.1.2 as well.
If this blog was helpful, check out our full blog archive.