Large number of children can cause the update performance issue (thoughts)

Large number of children can cause the update performance issue (thoughts)

Old forum URL: forums.lhotka.net/forums/t/356.aspx


Plain posted on Tuesday, June 13, 2006

Hi all!

I just wanted to share my thoughts on the parent-child design aspect of the CSLA. The framework dictates that a parent object initiates loading of its children at that moment that immediately follows the event of loading itself from a database. It also dictates that all children are saved at the moment that immediately follows the event of saving the parent object data. The side effect of this design is that ALL children objects data is sent via a wire first from the server data portal to the client side while a parent is loaded and then again is sent back from the client to server data portal. Let's assume that a hypotethical parent has <<many>> relatively heavy children objects and it's already been loaded along with its children and is currently residing on the client side. Now a UI makes a change to the parent itself and then initiates the Save for that parent. What happens next? The parent object as well as ALL its children are serialized and sent over the wire to the server side of the data portal. Only when the whole structure is de-serialized on the server data portal side and parentObject.DataPortal_Update() takes control those child objects check themselves if they need to be updated (via IsDirty). Then the whole structure is sent back to the client! That's right - we need to keep that DSL/Cable/T1/T4/dial-up :-) busy! Well, this example may be an exaggeration to a degree but seems to me that in this case using some class that inherits from CommandBase and just runs a couple of SQL Update statements on the server portal side would do the job much more effectively (performance wise). Does anybody out there have thoughts/examples on how to come around the (potential) problem with "many children" update? Or may be I'm just making this problem up?

 

 

 

bcdennis replied on Tuesday, June 13, 2006

    There is no reason for you to a.) download all child objects b.) save all child objects upon saving the parent.

Implement your child object lists using the Lazy Load pattern then they'll only be loaded upon request for the data and when you save your parent object, don't blindly update each child in the list, only update dirty children.


Plain replied on Tuesday, June 13, 2006

I appreciate everybody's responses. Thank a lot! Good, very dynamic forum!!!

Bcdennis, I agree that lazy loading technique may be a solution in some cases. But it was NOT my main concern. I was primarily concerned by the Update procedure (see below). By the way, one could argue that the lazy loading can backfire. This is when the UI needs those children right away - lazy load pattern implementation will cause the second trip over the wire (remote data portal scenario) in comparison to just one trip in the <<classic load all at once>> design. Now back to the update question ... First of all I wanted to clarify myself. I'm talking about a physical model with a remote server data portal. This is not an issue when a server data portal runs in-process. It's my understanding that if CSLA 2.0 is used <<as is>> then there is no way for me to stop ALL children from being serialized by .NET at the time of update. It will just happen. It's the amount of data that gets (unnecessarily?) pushed through the wire during an update operation that concerns me. It's obvious that only dirty children will be updated on the server data portal side. However all children are transferred no matter what the IsDirty flag value is.

Q Johnson replied on Tuesday, June 13, 2006

This topic is addressed fairly frequently in threads that contain (often in their titles) mention of a technique called "lazy loading."  A search on that terms locates a couple of threads here in the "new" forum. 
 
You will find several more at the "old" CSLA site, including these relatively recent ones (within a year or two) which surely refer to CSLA 1.x, but that shouldn't be a big issue:
 
http://www.searchcsla.com/Details.aspx?msn_id=23611
 
http://www.searchcsla.com/Details.aspx?msn_id=16640
 
 
Most of them end with this realization (quoted from one of the referenced threads): "Yeah, I slept on it overnight. I decided to NOT Lazy load, and just create read only classes for list, etc. I just need to figure out the complexities of my objects. Just part of the process of good design. I need to think about some of the business rules, and figure out how to share them easily. Thanks for your help! "
 
It seems likely to me that really there is likely an object design issue if you have to have LOTS of "relatively heavy" children.
 
But lazy loading must be a useful technique because Rocky mentions in his blog that 2.0.1 has improved support for it.

Plain replied on Tuesday, June 13, 2006

I appologize. I should have better searched the forum before posting a question. Thanks for the links!!!

ajj3085 replied on Tuesday, June 13, 2006

Others have already responded to this with good insights, but just to play along, lets suppose you do keep lots of 'heavy children.'  Yes, loading requires that you bring them all back (this can be done in 1 or 2 Sql calls usually).  So if there's alot of data, it may take some time.  Indeed I do have a situation where this is the case (thus the UI puts the call on a seperate thread and has a animation while the loading is done).

But saving though won't require nearly as much.  Its doubtful you would have modified even most of the children.  So you modify the parent and 20 children (out of 100).  There's no reason for the 80 unchanged children to send anything to the db, and its easy to code this by checking the IsDirty property of the object.  If its not dirty, just return without doing any work.

At any rate, you really should rethink your object model.  Its unlikely you really need a parent object which will contain many children that all also need to be editable.  Its pretty likely the children can be edited independatly of the parent.  I've often foudn this to be the case.

Andy

xal replied on Tuesday, June 13, 2006

Well, just adding a bit more to the subject:
The common design pattern leads to thinking: if the object is not deleted and it's not new, then it must be updated.
You should be doing: If Not Me.IsDirty Then Exit Sub inside your children Update method.
I also do this for root objects but by checking MyBase.IsDirty. This is because it's very common to update children, but not so for root objects.
So I do the check, to update the parent and let the children handle themselves....:

If MyBase.IsDirty Then
        <do whatever to update the root>
End If
Child1.Update(tr)
ChildCollection1.Update(tr)



Also, if you're using remoting and you have too many children that are unlikely to be altered you can implement a "FilteredSave". I implemented this some time ago for 1.x, you can read about it in the last messages of this thread (code included).



Andrés

Plain replied on Tuesday, June 13, 2006

Andrés,

My complements on your Filtered Save code. Are you also using it with the CSLA .NET 2.0 projects? Did you get the technique to work with unlimited number of child relation levels? I figured you were not getting a lot of help from the community on that subject and had to bear the heavy load alone. Did you get any feedback from Rocky on the subject? Seems to me like he (the Author) had his thoughts along the same lines with yours on the subject of transactions support in CSLA 2.0. Not on this subject of parent/child update in remote data portal setup though. I realize that there will be (were) some (technical) difficulties in a whole GetChanges-wire-Update-wire-Synchronize procedure (data binding, N-level undo, validation to name a few). And because of those difficulties this really should be a part of the CSLA so that business objects developer do not have to worry about those details.  I guess there is always a room for improvement and I personally hope that some optimization will be done in on-going CSLA releases in the area of physically-distributed-smart-object updating.  Thanks again! Big Smile [:D]

xal replied on Tuesday, June 13, 2006

Thanks plain.
No, it never seemed to catch anyone's attention. Anyway, I'm glad you find if useful.
About the n-level filtering, I don't think it's a good idea because you'll end up doing a lot of work for little gain. If your object contains many children and they also contain many children, the whole operation will cost more than transfering the data through the wire, so 1 level is acceptable, more is insane.
It's different for datasets because you don't have grand children, just datatables that contain datarows. Like a root that contains many collections with child items.
Once you have grand children it gets too complex. Anyway, in cases where you go up to grand children and beyond, it is unlikely that you'll have such a large list of child items, so it may not be such a big problem. You can still filter children that are not dirty and that don't contain dirty grandchildren.

Andrés

Mark replied on Tuesday, June 13, 2006

You are right (in regards to keep the object model simple) - but just to clarify one bit, the original poster was concerned about the size of the object graph going "over-the-wire" so to speak, not just DB calls.

If I load a parent that has 100 children, and change just one of the children, the parent and all 100 children are still sent back over the wire to the data portal.  Not that big of deal when running locally but if you're using remoting, it can add up.  As you noted, however, only the one child will actually make a call to the DB. 

For what its worth...

 

 

xal replied on Tuesday, June 13, 2006

Yes, I was aware of that. That's why I posted the link to the filtered save... which is similar to the getchanges / merge way of doing things that the dataset has, only all that is abstracted from the user calling save.


Andrés

Plain replied on Tuesday, June 13, 2006

Thanks Andrés!

I'll take a look. Sounds like this is exactly what I need. I will keep you posted on this.Smile [:)]

Copyright (c) Marimer LLC