On Oct 7, 2012, at 2:17 AM, me wrote:
> using python 2.7, sqla 0.7.9, postgresql 9.1
>
> i've setup joined table inheritance and wanted an eager loaded relationship
> from one of the derived objects to another derived object. when i do that i
> get what seems to be a really inefficient query.
>
> here is the minimal setup:
>
> http://pastebin.com/yS7gDfju
>
> and this is the output:
>
> SELECT
> ...
> FROM root
> JOIN type2 ON root.id = type2.id
> LEFT OUTER JOIN (SELECT root.id AS root_id, root.type AS root_type, type1.id
> AS type1_id, type1.field1 AS type1_field1
> FROM root JOIN type1 ON root.id = type1.id)
> AS anon_1 ON type2.type1_id = anon_1.type1_id
>
> what i expected was:
>
> SELECT
> ...
> FROM root
> JOIN type2 ON root.id = type2.id
> LEFT OUTER JOIN root as root_1 ON root_1.id = type2.type1_id
> LEFT OUTER JOIN type1 ON type1.id = root_1.id
>
> which runs *much* faster for the data sets i've tried.
>
> is there a way to force the relationship to generate the 2nd form?
there's not, and the best this would ever do if SQLA were to have a particular
set of improvements that are fairly involved, would be this form:
select .. from root JOIN type2 ON <onclause> LEFT OUTER JOIN (root JOIN
type1 ON <onclause>) ON <onclause>
that is, the target eager join would be parenthesized without the SELECT
subquery part of it. Most databases with the exception of SQLite and older
MySQL versions support parenthesization of this form.
The grouping is necessary as it is very difficult to "de-parenthsize" the joins
in the way you describe without changing the meaning of complex queries. Just
removing the SELECT has shown to be a complex task. Supporting auto-rendering
of a JOIN b LEFT OUTER JOIN (c JOIN d) within joined eager loading is related
to ticket #2369, so I've added this variant as a use case.
Normally, if this were just an explicit query.join(), the way to get exactly
the query you want would be to use the Table objects to construct exactly the
join you want, as introduced at
http://docs.sqlalchemy.org/en/rel_0_7/orm/inheritance.html#advanced-control-of-which-tables-are-queried
. This can be combined with contains_eager() to provide joined eager loading
against a specific query. But in this case the eager loading wouldn't be
automatic.
> or am i doing something i shouldn't?
I don't often use "lazy='joined'" as part of a relationship(). I'd only use
it on many-to-one, as is the case here, but also with many-to-ones I'll often
leave those as "lazy", if the case is such that I'm loading lots of Type2s that
refer to a small set of Type1s, I'd only get as many SELECT statements as there
are Type1 identities referred to in the whole set being loaded.
Another trick that I haven't tried but might work is to make the relationship
to Root, and then modify the primaryjoin to also specify the polymorphic
identity of "type1":
relationship("Root", primaryjoin="and_(Type2.type1_id == Root.id,
Root.type=='TYPE1')")
I haven't tried that but it might work.
Finally, if performance is critical, I'd be shying away from excessive use of
joined inheritance in the first place. I actually built a datamodel that was
PG and based a large and complex series of models on a shared
joined-inheritance base, and it was this kind of AjoinB->AjoinC thing all the
way, and eventually you could kind of feel how much work you were making the
database do just for a little bit of purity, it probably wasn't worth it. The
way it ended up working was that we made extensive usage of relationship
caching using the Beaker caching example in the docs (which will become
dogpile.cache in 0.8), and then turned off most eager loading. The
many-to-ones were typically pulling from a limited set of entities that was
just 100% cached within a few minutes of the app first starting up.
Can't quite give you the answer you want, just a bunch of ways to almost get
there; hope one of them works out.
>
> thanks
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/sqlalchemy/-/0laXtaxdh8UJ.
> 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/sqlalchemy?hl=en.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" 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/sqlalchemy?hl=en.