Ticket Q523207
Visible to All Users
Duplicate

Efficient loading of joined data (version 2)

created 11 years ago

After much testing, I think that I have determined the exact scenario that has been causing us so much trouble.
Specifically, the problem involves Explicit loading of properties that are themselves base types. What seems to happen is that if you have the following classes:
public class Order : XPObject {…}
public class StandardOrder : Order {…}
public class RushedOrder : Order {…}
And then in another class you have the following reference:
public class Customer {

  [ExplicitLoading]
  public Order LastOrder {get; set; }

}
The effect of this, is that it efficiently loads all Customers and "correctly" left-join's in their last order. The problem occurs if some of the customers have RushedOrders. IN those cases, XPO then reaches BACK to the database, using an IN operator, to get all of the RushedOrder data for any records that are of that type.
So - the more specific question is - is there any way to not just MapInheritance to the parent table for sub-classes, but also to have it always "pre-load" the data from all child classes when loading the base class (so that it does NOT have to "reach back" to the database when child-types are encountered)?
Even doing 2 queries would be better (it seems to me). One query could (with the appropriate criteria - determine the XP-object types) so that the "get data" when loading the base class could also pre-load the data for the child types.
Thanks - and I look forward to hearing from you. Take care.

ps. The sample project demonstrates the issue. If you run SQL Profiler, you will see that it generates 2 SQL classes. By just changing the "LastOrder" property from an Order type (base type) to the specific type RushedOrder causes only 1 sql command to be executed.

Thanks again.

Answers approved by DevExpress Support

created 11 years ago (modified 11 years ago)

Hi.
>>>
So - the more specific question is - is there any way to not just MapInheritance to the parent table for sub-classes, but also to have it always "pre-load" the data from all child classes when loading the base class (so that it does NOT have to "reach back" to the database when child-types are encountered)?
<<<
I am afraid there is no option to change this behavior in the current version and it is unlikely will be supported in the future. If we join all descendant tables, this will lead to a too complex query. Even if the database server will be able to process this query, the performance benefit (compared to a separate query that loads related objects by keys) is questionable.

    Show previous comments (11)
    DevExpress Support Team 11 years ago

      Since server mode collections operate on the server side, they cannot handle non-persistent properties (they exist on the client side only).

        I'll have to step in to critizie Michael's IMAGINARY SCENARIO comment. Maybe 100K records being loaded could be considered an imaginary scenario (I will show it is not!), but the underlying problem affects real-world scenarios too, mainly on Internet Facing applications.
        A SELECT N+1 happens when using server mode with Calculated Properties, mainly with free-joins like the following properties I have on a real-worl application:
               [PersistentAlias("IsNull([<Funcionario>][Pis = ^.Pis && Cliente = ^.Cliente].Single(Oid), 0)")]
               public int OidFuncionario
               {
                   get { return (int)EvaluateAlias("OidFuncionario"); }
               }
               [PersistentAlias("[<Funcionario>][Oid = ^.OidFuncionario].Single()")]
               public Funcionario Funcionario
               {
                   get { return (Funcionario)EvaluateAlias("Funcionario"); }
               }
        Meaning that for each calculates property you'll have an extra round-trip to the database server to fetch it. The irony is that XPO will correctly handle these correctly, without extra round-trips or filtering on the client-side, when they build filter criterias based on these "calculated fields". It means we can use SERVER MOVE to filter over these fields, but we can't use them without loosing performance when displaying them on a grid.
        What happens when you have over 10 such calculated properties? A round-trip will be performed FOR EACH calculated property for each displayed row. Our APSxGridView all of them use ServerMode, even so there was 10 extra selects for each record shown… We allowed the end-user to show 50 records by default, but he could choose to show 10, 20, 50, 100, 200, 500 or 1000 records at a time (it was a busisness need). Even the default 50 records would result in 501 individual queries against the database!!! The pageload time wa around 28 seconds!!! When removing all the calculated properties, the pageload time went down to 1 second tops! When displaying 1000 records the page was unusable with the calculated properties, but worked perfectly without them.
        In https://www.devexpress.com/support/center/Question/Details/S36566#comment-16a0136b-15e0-410a-87ba-2df1336b8788 I've suggested allowing calculated properties that aren't read-only so that DevExpress could assign a value to them with a single fetch from the database the same way it does for ordinary properties. My suggestion was ignored.
        So, that gets us back to the IMAGINARY SCENARIO… Well it may be imaginary in the head of DevExpress staff, but suppose I've got a 22.000 records table, paginated correctly using server mode, and then the end user filters the grid to show, let's say, 4000 records then clicks the export button… If I have 5 extra round trips per record, that would be 20001 queries against the database just to export the grid data in a PDF!!! The same happens with XtraReport! Instead of doing a single query with all needed joins, XPO will perform the ORM antipattern of SELECT N+1 to fill up this data, creating a performance bottleneck and a showstopper for many situations.
        Not so imaginary anymore, don't you think? While the 100K records may seem hypothetical similar things happen in real-life within legitimate scenarios. Reporting and exporting being a few of them.
        In our application we've been judiciously removing calculated properties from grid, loosing functionality and having to handle customer wrath for loosing things they were relying on (while their dataset was smaller).
        So the imaginary scenario is a real problem for us, and the first scenario I described, with the SELECT N+1 just to show 50 rows resulting in over 500 individual queries is also a real problem.

        DevExpress Support Team 10 years ago

          @Felipe: Thank you for your feedback, again. We are aware of the performance issue related to complex calculated properties and the S36566 feature request, which you pointed out, is still on our sights. We cannot however implement it immediately. I hope it will be planned for one of future versions. The comment you posted to that ticket was not ignored. It's only the example you provided was not representative for the problem being discussed. Currently, we don't have a general solution to improve the performance with displayable calculated properties. In each specific scenario, the solution can be different.

          Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

          Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.