On Friday, April 22, 2016 at 12:32:33 PM UTC+3, Tiago Cardoso wrote:
>
> Hi Jeremy,
>
>
> We've recently had some issues inserting/updating multiple elements in our 
> vanilla rails/pg app (yes, with active record), in that per record, we'd 
> try to find or create a new instance, pass the results, save in db, and 
> execute all callbacks on the AR side (bubbling up timestamps, update those 
> counter caches, yadayada). Fairly vanilla, unbounded number of queries, 
> very low performance (depending of the number of multiple records, but 
> sometimes I'd get times of 60 seconds (!) for job completion). As this was 
> consumption of internal service, it wasn't apparent for the user, reason 
> why we ignored the performance. 
>
> Our main drawback was the lack of good support in postgres for upserts, 
> that is, until 9.5 came along. We were obviously excited, benchmarked some, 
> and we'd get in theory a performance uberboost (where, for N records, we'd 
> have 2 queries associated, 2N, we would bring this number down to 1!). 
> Our bottleneck therefore became... Active Record. We searched for support 
> for "ON CONFLICT" using idiomatic AR/AREL, and couldn't find a thing. I 
> reasoned that, either we'd have to use raw SQL, or we could just use sequel 
> on top of Active Record to build the query. 
>
> So I iterated on a solution using AR everywhere except in the multi-upsert 
> query, where I used sequel, and voilĂ . 
>
> AR
>   instantiate all relevant parent model, lock the table row  #=> parent = 
> ParentClass.find(id) ; parent.lock!(true)
> SEQUEL
>   build all the attributes necessary
>   build multi upsert query and trigger #=> 
> DB[:children].insert_conflict(...
> AR
>   reset counter caches, update timestamps #=> 
> ParentModel.reset_counters(...  ; parent.touch
>
>
> Speedier, and the memory consumption was also way lower, as no model 
> instances were instantiated. 
>
> Thanks Sequel!
>
>
> Now to the reason why I wrote this post: I don't think it's correct to do 
> this as described above, as AR model locks the table row, and the multi 
> insert is done with the sequel db handler, that means, two separate 
> connections to the DB. The way I see it, I have these possible solutions:
>
>
> 1. Use the Sequel layer only to build the SQL, and then pass it to the AR 
> connection.
>

This is probably the easiest short term solution.  As you mentioned later, 
multi_insert_sql is the method.  I'm guessing the reason it connects to the 
database is to know how to correctly escape the strings (it uses a 
connection-specific string escaping method).  I doubt there will be much 
impact in a multi-threaded app, but you'd have to see.
 

> 2. Pass the AR connection object to the Sequel db handler (is this 
> possible? both use the 'pg' handler under the hood)
>

This is not possible.  Sequel uses a Sequel-specific PG::Connection 
subclass.  Some people have made hacks that allow ActiveRecord to use the 
Sequel connection pool, but it's not something I'd feel comfortable doing 
in my application.
 

> 3. Remove Active Record and replace all my model layer with Sequel (and 
> migrations, etc etc etc)
>

This is definitely the best long term solution, but as you mentioned, it's 
probably not worth it unless you want to rewrite the app.  I can recommend 
a good web framework if you plan on doing that. :)
 

> 3 is out of the question, as we don't have the resources, and replacing 
> ORM is not an easy task. I'd envision rewrite the app with sequel, but 
> certainly not with rails. 2 might be something which is not trivial and 
> allowed by the public API (haven't researched it). 1 seems the most 
> feasible, provided that Sequel supports this. 
>
> So, the question being: can I use Sequel as a better Arel?
>
> Thanks for all the awesome work! Sequel is a life saver.
>

Thanks!

Jeremy 

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.

Reply via email to