On Nov 17, 2007, at 12:02 AM, Sharon Rosner wrote:
>
>> This code results in two database hits like so:
>>
>> I, [2007-11-16T13:15:11.468035 #1255] INFO -- : INSERT INTO orders
>> ( `market`, `date`, `order_id`) VALUES ( 'ICE', '20071114', '9104')
>> I, [2007-11-16T13:15:11.468913 #1255] INFO -- : SELECT * FROM orders
>> WHERE (`id` = 28838) LIMIT 1
>>
>> The order instance obviously already knows the primary key since it
>> uses it for the SELECT statement.
>
> Currently when you create a model record, it is SELECTed immediately
> after being INSERTed, in order to retrieve all the columns and any
> default values belonging to the model instance. I think this makes
> sense in many cases, but there's the performance penalty. If it's
> really important to you, I can look at offering an alternative
> behavior.
Yes, let's take a look at some alternatives. I agree that this
behavior should be default. It certainly follows the Principle of
Least Surprise. But for us performance-conscious folks, the extra
select can oftentimes be superfluous particularly if we aren't using
column defaults.
I took a look at the Sequel::Model definition for +save+ where +refresh
+ does this immediate select. It would be handy if we could pass in
optional parameters when defining our Models to selectively turn off
this type of behavior. Here's an example:
class Order < Sequel::Model(:orders)
set_schema do
# column definitions...
end
performance_tune :disable_auto_refresh => true
end
module Sequel
class Model
attr_accessor :opts
def performance_tune(opts)
@opts = @opts.merge(opts)
end
# Creates or updates dataset for Model and runs hooks.
def save
run_hooks(:before_save)
if @new
run_hooks(:before_create)
iid = model.dataset.insert(@values)
# if we have a regular primary key and it's not set in @values,
# we assume it's the last inserted id
if (pk = primary_key) && !(Array === pk) && [EMAIL PROTECTED]
@values[pk] = iid
end
if pk
@this = nil # remove memoized this dataset
refresh unless opts[:disable_auto_refresh]
end
@new = false
run_hooks(:after_create)
else
run_hooks(:before_update)
this.update(@values)
run_hooks(:after_update)
end
run_hooks(:after_save)
self
end
end
end
I don't know if you want to "litter" the code with this style of
"unless opts[:something]", but it is one way to skin this cat. In the
meantime I have monkey-patched my copy to do exactly this. It appears
to work okay and has improved my application performance by about 6%
(heavy inserts and updates where I cache the table's primary key for
future updates and joins).
If you'd like me to provide this as a patch and a spec, let me know
and I'll be happy to whip up a spec for it.
And if I haven't said it before, thanks for creating Sequel. It's is
*so much* easier to hack this codebase than ActiveRecord!
cr
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sequel-talk?hl=en
-~----------~----~----~----~------~----~------~--~---