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 sqlalchemy@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > 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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.