diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2017-11-17 03:12:57 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-17 03:12:57 +0900 |
commit | bbae710a405ce92074c1666dcf859196c29e2ed2 (patch) | |
tree | 39862ca83075119e54a5cec8530530b271508ba8 /activerecord/lib/active_record/relation.rb | |
parent | 8bfa617e9990b05061c2f481afe87e055b6a6106 (diff) | |
download | rails-bbae710a405ce92074c1666dcf859196c29e2ed2.tar.gz rails-bbae710a405ce92074c1666dcf859196c29e2ed2.tar.bz2 rails-bbae710a405ce92074c1666dcf859196c29e2ed2.zip |
Avoid creating extra `relation` and `build_arel` in `_create_record` and `_update_record` (#29999)
Currently `_create_record` and `_update_record` in `Persistence` are
creating extra `unscoped` and calling `build_arel` in the relation. But
`compile_insert` and `compile_update` can be done without those
expensive operation for `SelectManager` creation. So I moved the
implementation to `Persistence` to avoid creating extra relation and
refactored to avoid calling `build_arel`.
https://gist.github.com/kamipo/8ed73d760112cfa5f6263c9413633419
Before:
```
Warming up --------------------------------------
_update_record 150.000 i/100ms
Calculating -------------------------------------
_update_record 1.548k (±12.3%) i/s - 7.650k in 5.042603s
```
After:
```
Warming up --------------------------------------
_update_record 201.000 i/100ms
Calculating -------------------------------------
_update_record 2.002k (±12.8%) i/s - 9.849k in 5.027681s
```
30% faster for STI classes.
Diffstat (limited to 'activerecord/lib/active_record/relation.rb')
-rw-r--r-- | activerecord/lib/active_record/relation.rb | 61 |
1 files changed, 0 insertions, 61 deletions
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index e2d2f45503..081ef5771f 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -36,67 +36,6 @@ module ActiveRecord reset end - def insert(values) # :nodoc: - primary_key_value = nil - - if primary_key && Hash === values - primary_key_value = values[values.keys.find { |k| - k.name == primary_key - }] - - if !primary_key_value && klass.prefetch_primary_key? - primary_key_value = klass.next_sequence_value - values[arel_attribute(klass.primary_key)] = primary_key_value - end - end - - im = arel.create_insert - im.into @table - - substitutes = substitute_values values - - if values.empty? # empty insert - im.values = Arel.sql(connection.empty_insert_statement_value) - else - im.insert substitutes - end - - @klass.connection.insert( - im, - "#{@klass} Create", - primary_key || false, - primary_key_value, - nil, - ) - end - - def _update_record(values, id, id_was) # :nodoc: - substitutes = substitute_values values - - scope = @klass.unscoped - - if @klass.finder_needs_type_condition? - scope.unscope!(where: @klass.inheritance_column) - end - - relation = scope.where(@klass.primary_key => (id_was || id)) - um = relation - .arel - .compile_update(substitutes, @klass.primary_key) - - @klass.connection.update( - um, - "#{@klass} Update", - ) - end - - def substitute_values(values) # :nodoc: - values.map do |arel_attr, value| - bind = predicate_builder.build_bind_attribute(arel_attr.name, value) - [arel_attr, bind] - end - end - def arel_attribute(name) # :nodoc: klass.arel_attribute(name, table) end |