"build" is slow on large has_many association collections

All,

Rails 1.1.6

Given: an AR::Base descendant X has_many :Ys

As the size of the collection of Ys increases, the time it takes to run
the “build” method (used to create a new instance of Y, as in
x.ys.build(:attr1 => ‘blah’) takes longer and longer.

For my specific case, if I call x.ys.build(:attr1 => ‘blah’):

If X has 1000 Ys, it takes about 2 seconds to build a new Y
If X has 42000 Ys, it takes about 90 seconds to build a new Y

I’ve tracked down the issue to the “find_target” method in
has_many_association.rb.

It looks like Rails is trying to determine if the object (the new Y)
that the user is requesting to be created already exists in the
collection and somehow this is less than optimal.

A couple of questions:

  1. Is this a known issue?
  2. If so, is it resolved in a later version of Rails?
  3. It appears that providing the :finder_sql option on the has_many
    declaration may help - any thoughts on that?

Thanks in advance,
Wes

I found that the call to “load_target” in method “build” (defined in
has_many_associations.rb) was not necessary.

A quick look at the Rails 1.2 AR code makes it look like this is no
longer a problem in those versions.

But it was definitely do a find(:all) [ and using the :finder_sql option
didn’t change that ] on the collection class (Y), for apparently, no
reason.

I guess no one’s on 1.1.6 anymore ;), but just in case, you could monkey
patch your way out of this one.

Wes

Yep. I believe this issue crept up again in 1.2.5 but was removed in
1.2.6. It was loading the entire association unnecessarily.

-Bill

Wes G. wrote:

I guess no one’s on 1.1.6 anymore ;), but just in case, you could monkey
patch your way out of this one.

Wes


Sincerely,

William P.

William P. wrote:

Yep. I believe this issue crept up again in 1.2.5 but was removed in
1.2.6. It was loading the entire association unnecessarily.

-Bill

Wes G. wrote:

I guess no one’s on 1.1.6 anymore ;), but just in case, you could monkey
patch your way out of this one.

Wes


Sincerely,

William P.

It’s crazy, because you would see slowness super quickly as your DB
grew. Surprised that it made it back in.

Wes

I know. I believe this is the TRAC ticket:

http://dev.rubyonrails.org/ticket/8713

Wes G. wrote:

patch your way out of this one.

It’s crazy, because you would see slowness super quickly as your DB
grew. Surprised that it made it back in.

Wes


Sincerely,

William P.