[Dbix-class] order_by interfering with has_many fetch
Darin McBride
darin.mcbride at shaw.ca
Sun Nov 15 22:23:58 GMT 2015
On Saturday November 14 2015 11:39:04 PM Peter Rabbitson wrote:
> On 11/14/2015 10:46 PM, Darin McBride wrote:
> > DBIx::Class::ResultSet::_construct_results(): Unable to properly collapse
> > has_many results in iterator mode due to order criteria - performed an
> > eager cursor slurp underneath. Consider using ->all() instead at
> > /data/Lacuna- Server/lib/Lacuna/DB/Result/Empire.pm line 622
...
>
> It is (I suspect) a different issue, and if the case - the warning (it
> is not an error) needs better wording. If 'name' does NOT have a unique
> non-nullable constraint declared on it - i.e. you can have several 'me's
> with identical 'name's - then DBIC can not rely on the results coming
> from the DBI cursor to be "grouped in slabs" representing every object
> hierarchy "hanging off" every individual 'me' instance. This is why it
> needs to exhaust the cursor to give you a "certifiably correct" answer.
Maybe it's just my non-DBIC background, I just figured the DB was giving me
everything in the right order already ;) But I guess DBIC is trying to
collapse objects so that multiple rows with those prefetches will return the
same actual object reference? Or something else entirely, which I don't
understand :)
> > If it helps, Map::Body has 0 or 1 empires (can be null)
>
> Your analysis is correct - the order on 'empire.id' ought to work, but
> this is extra (rather complicated) logic that currently is not
> implemented: note this TODO
> https://metacpan.org/source/RIBASUSHI/DBIx-Class-0.082820/t/prefetch/multipl
> e_hasmany_torture.t#L131-132
In my case, it doesn't really matter whether I sort on me.id or empire.id in
addition, so I can live without it for now.
> > Any guidance on how to update this order_by to get DBIC to only fetch one
> > row at a time would be appreciated.
>
> Simply order by [ me.name, me.<primary_key> ] <--- this will ensure
> things are ordered in a *stable* manner on the leftmost side, and the
> collapse will proceed correctly. A PR/patch amending the warning text
> and/or the prefetch documentation to make this clearer will be *very*
> much appreciated.
To me, me.name is a unique key, so that should indicate stability, no? Now, I
can fully appreciate that the actual definition of the table may not indicate
to DBIC that it's a unique key, though I tried using add_unique_constraint for
name, and that didn't help any. (There is both an integer primary key and the
name is also unique across all rows.) So, other than primary_key, of which I
already have one, what other method is used to determine that collapsing
doesn't require a full scan?
As to the documentation, I'm not sure I understand it sufficiently myself to
start proposing changes :)
> Please note that depending on your DBD, DBI may *still* be loading the
> entire resultset into memory even if DBIC uses ->next on the surface.
> For example DBD::Pg does this invariably, and DBD::mysql does it by
> default unless you set https://metacpan.org/pod/DBD::mysql#mysql_use_result
This is useful information. Since we're using mysql, this may be a separate
issue that I'll have to take up. However, in the meantime, what I can do is
what I can do, and adding 'me.id' does seem to get past this warning, which, I
assume, means fewer perl objects created at a time.
Thanks,
More information about the DBIx-Class
mailing list