--
You received this message because you are subscribed to the Boston Ruby Group mailing list
To post to this group, send email to boston-r...@googlegroups.com
To unsubscribe from this group, send email to boston-rubygro...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/boston-rubygroup
I would look into a ActiveRecord::Base.connection.execute call.
This will return the raw result in an array format. The problem that
you're probably running into with a normal ActiveRecord::Base.find is
that it instantizes each record and that is a lt of memory. So with
the numbers you're talking about you might start swapping which is
going to bring everything to a crawl.
- Brian
Sent from my iPhone
Well, that's what find_each is meant to take care of --- it
instantiates just a few records at a time, so you don't have to fit
the whole set in the memory of a single process. Though, of course,
you're still out the CPU time for constructing all the objects,
and the time spent later when the GC is mopping them up. Just calling
AR::Base.initialize 50,000 times (or more, if objects from multiple
tables are involved) can add up.
(Then again, if the query is using :include to try to instantiate
objects from multiple tables in a single fetch, it might be worth
doublechecking in the debug log to make sure that :include and
find_each are playing well together. If you want a 50,000 row
request to finish in ten seconds, you've got 200 microseconds per
row; an extra SQL query per row to find the record at the end of
some belongs_to is probably not going to work.)
One last thought: if you aren't completely comfortable writing the
query in raw SQL, it might be worth writing a quickie prototype in
pure AR, for sanity-checking on the spec, and to verify that the
raw SQL is doing what you want....
rst
--
+1 select_values
Great for memory usage / reduced object creation.
Sooner or later you will have to use resque or delayed_job as your mongrel will time out.
--Keenan
FYI if anyone is interested I got a prototype working today that uses
ActiveRecord::Batches.find_in_batches to loop through the large result
set in chunks. Then by using render :text with a proc I was able to
have the data streamed out to the client gradually... so the browser
displays a “downloading file” progress bar to the user.
The key to all of this was that the user’s expectations were lowered
by seeing the downloading file dialog box... they were willing to wait
for the large file to download. So the performance is still slow, but
the perceived performance was fast since the download dialog box
appeared right away. After that point the user is willing to wait for
a large file.
Also find_in_batches prevents Ruby from running out of memory.
Josh - I agree having an offline process generate the reports is
ideal, but was too much coding for me given my deadlines. And my app
is running in a low-usage intranet environment, so it’s probably ok
for now to have a Passenger server process tied up looping through the
SQL results once in a while. I'll have to look into doing this later.
Brian, Keenan - it turned out most of the time was spent in the DB, so
refactoring the code to use select_values or something similar
wouldn't have been worthwhile for me in this case.
thanks again! - pat
Sadly, at my day job I need to use Oracle... To use your plugin with
Oracle would I have to extend the Oracle Enhanced Adapter similar to
what you are doing in mysql_adapter_extensions.rb for the MySQL
adapter? Is there anything else I’ll need to do? Is there any reason
you can think of why this wouldn’t work with Oracle?
thanks!! - pat
http://patshaughnessy.net/
Yes I think all you need to do is to extend select_all to accept a
block, like what I did for the MySQL adapter.
--
Phusion | The Computer Science Company
Web: http://www.phusion.nl/
E-mail: in...@phusion.nl
Chamber of commerce no: 08173483 (The Netherlands)