1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Use statement cache for find_by(author: david)

```ruby
ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
  end

  create_table :comments, force: true do |t|
    t.belongs_to :post
  end
end

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

post = Post.create!

Benchmark.ips do |x|
  x.report("find_by post") { Comment.find_by(post: post) }
end
```

Before:

```
Warming up --------------------------------------
        find_by post   395.000  i/100ms
Calculating -------------------------------------
        find_by post      4.026k (± 3.1%) i/s -     20.145k in   5.008059s
```

After:

```
Warming up --------------------------------------
        find_by post     1.183k i/100ms
Calculating -------------------------------------
        find_by post     11.859k (± 2.5%) i/s -     60.333k in   5.090685s
```
This commit is contained in:
Ryuta Kamizono 2020-06-05 11:20:07 +09:00
parent 60bfed90ce
commit dbda5febe4

View file

@ -202,11 +202,20 @@ module ActiveRecord
hash = args.first
return super unless Hash === hash
values = hash.values
values = hash.values.map! { |value| value.is_a?(Base) ? value.id : value }
return super if values.any? { |v| StatementCache.unsupported_value?(v) }
# We can't cache Post.find_by(author: david) ...yet
keys = hash.keys.map! { |key| attribute_aliases[name = key.to_s] || name }
keys = hash.keys.map! do |key|
attribute_aliases[name = key.to_s] || begin
reflection = _reflect_on_association(name)
if reflection&.belongs_to? && !reflection.polymorphic?
reflection.join_foreign_key
else
name
end
end
end
return super unless keys.all? { |k| columns_hash.key?(k) }
statement = cached_find_by_statement(keys) { |params|