These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: How to batch massive update
PostPosted: Tue Dec 18, 2007 8:42 am 
Newbie

Joined: Sun Nov 18, 2007 3:22 am
Posts: 8
Hi,
I have a process that runs once a week to save a specific snapshot of my data.
I retrieve a list of objects from the original tables.
there is a parent-child mapping that saves these retrieved list to a parent object and a list of its children.
each list contains around 20000 items.
When i try to update the child table it generates 20000 updates which causes big performance issues.
How can i speed up the update by using batch or HQL or whatever...
THX!!!!

here is my code:
public void BackupLocationN(int LocationID)
{
try
{
EntityContextObj context = new EntityContextObj();
int NumberOfDaysBack = -GetLocationSnapShotPeriod(LocationID);
DateTime dt = DateTime.Now.AddDays(NumberOfDaysBack);
using (ISession session = NHibernateHelper.GetCurrentSession(context))
{
ICriteria criteria = session.CreateCriteria(typeof(ItemData));
criteria.Add(Expression.And(Expression.Eq("OrgID", LocationID), Expression.Gt("TimeStamp", dt)));
criteria.AddOrder(Order.Asc("ItemID"));
IList<ItemData> ItemsList = criteria.List<ItemData>();
if (ItemsList.Count == 0) return;
session.Clear();
//try to join criteria 2 and 3
ICriteria criteria2 = session.CreateCriteria(typeof(SnapShotLocation));
criteria2.Add(Expression.Eq("LocationID", LocationID));
SnapShotLocation SSL = (SnapShotLocation)criteria2.UniqueResult();
if (SSL == null)
{
SSL = new SnapShotLocation();
SSL.LocationID = LocationID;
SSL.Version = 0;
SSL.SnapShotDate = DateTime.Now;
}
SSL.SnapShotDate = DateTime.Now;
if (SSL.SnapShotID == 0)
{
for (int i = 0; i < ItemsList.Count; i++)
{
AddNewSnapShotItem(ItemsList[i], SSL);
}
}
else
{
ICriteria criteria3 = session.CreateCriteria(typeof(SnapShotItem));
//get all the current Items that r in the DB for this location.
criteria3.Add(Expression.Eq("SnapShotID", SSL));
criteria3.AddOrder(Order.Asc("ItemID"));
IList<SnapShotItem> SnapShotItemsList = criteria3.List<SnapShotItem>();
int SnapshotCounter = 0;
bool NotOnItemsAllIDList = false;
for (int i = 0; i < ItemsList.Count; i++)
{
NotOnItemsAllIDList = false;
if (SnapShotItemsList.Count > SnapshotCounter)
{
//update the snapshotItem with the data of ItemData and add it to the Parent.
if (ItemsList[i].ItemID == SnapShotItemsList[SnapshotCounter].ItemID)
{
UpdateSnapShotItem(ItemsList, SSL, SnapShotItemsList, SnapshotCounter, i);
SnapshotCounter++;
}
else
{
if (ItemsList[i].ItemID > SnapShotItemsList[SnapshotCounter].ItemID)
{
SnapshotCounter++;
i--;
NotOnItemsAllIDList = true;
}
else AddNewSnapShotItem(ItemsList[i], SSL);
}
}
else AddNewSnapShotItem(ItemsList[i], SSL);
if (!NotOnItemsAllIDList) session.Evict(ItemsList[i]);
}
}
session.SaveOrUpdate(SSL);
session.Flush();
}
NHibernateHelper.CloseSession();
}
catch (Exception ex)
{
NHibernateHelper.CloseSession();
}
}


Top
 Profile  
 
 Post subject: Batch update
PostPosted: Tue Dec 18, 2007 5:09 pm 
Newbie

Joined: Sat Sep 22, 2007 5:42 am
Posts: 10
Hello!

Have you seen this entry 15.1.5 in the documentation?

Hope it helps.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 18, 2007 11:43 pm 
Expert
Expert

Joined: Fri May 13, 2005 11:13 am
Posts: 292
Location: Rochester, NY
First, when posting large code snippets please use the \[code\] to format it for readability.

Second, section 15.1.5 isn't really going to help: that is in reference to batch fetching, which would not be useful here.

Finally, it is hard to tell what your specific problem is: are you making modifications on 20,000 objects then calling flush? Or are you not modifying all the objects or just modifying the collection and still seeing 20,000 updates?

It would be helpful if you could distill a minimal example.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 19, 2007 2:14 am 
Regular
Regular

Joined: Tue Feb 21, 2006 9:50 am
Posts: 107
I prefer to use plain ADO.NET for manipulating mass data. For example in an application i wrote i had to clone a complex model with many 1..n relations (in the database the model is represented by around 5.000 to 10.000 records). Using plain ADO.NET and DataSets boosts the performance around 200%.

Regards
Klaus


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 20, 2007 6:18 am 
Newbie

Joined: Sun Nov 18, 2007 3:22 am
Posts: 8
Hi i am attahcing the code i wrote:
the first criteria returns 20000 objects and then i modify all the 20000 objects(The date it was updated is important)

THX!!!
Code:
int LocationID=10000019;
            EntityContextObj context = new EntityContextObj();
            DateTime dt = DateTime.Now.AddDays(-7);
            using (ISession session = NHibernateHelper.GetCurrentSession(context))
                {
                        ICriteria criteria = session.CreateCriteria(typeof(ItemData));
                        criteria.Add(Expression.And(Expression.Eq("OrgID", LocationID), Expression.Gt("TimeStamp", dt)));
                        criteria.AddOrder(Order.Asc("ItemID"));
                        IList<ItemData> ItemsList = criteria.List<ItemData>();
                        //try to join criteria 2 and 3
                        ICriteria criteria2 = session.CreateCriteria(typeof(SnapShotLocation));
                        criteria2.Add(Expression.Eq("LocationID", LocationID));
                        SnapShotLocation SSL = (SnapShotLocation)criteria2.UniqueResult();
                        SSL.SnapShotDate = DateTime.Now;
                        ICriteria criteria3 = session.CreateCriteria(typeof(SnapShotItem));
                        //get all the current Items that r in the DB for this location.
                        criteria3.Add(Expression.Eq("SnapShotID", SSL));
                        criteria3.AddOrder(Order.Asc("ItemID"));
                        IList<SnapShotItem> SnapShotItemsList = criteria3.List<SnapShotItem>();
                        for (int i = 0; i < ItemsList.Count; i++)
                        {
                            SnapShotItemsList[i].ItemQuantity = ItemsList[i].ItemQuantity;
                            SnapShotItemsList[i].Timestamp = DateTime.Now;
                            SSL.AddItem(SnapShotItemsList[i]);
                            session.Evict(ItemsList[i]);
                        }

                        session.SaveOrUpdate(SSL);
                        session.Flush();
                }
                NHibernateHelper.CloseSession();
            }

the Mapping:
Code:
<class name="ItemData" table="PID_PerpetualInventory">
    <composite-id>
      <key-property name="ItemID" column="ItemID"/>
      <key-property name="OrgID" column="LocationID"/>
    </composite-id>
    <property name="ItemQuantity" column="Quantity" type="double"/>
    <property name="CountDate" column="InvCountDate" type="DateTime"/>
    <property name="CountAmount" column="InvCountQuantity" type="Double"/>
    <property name="Value" column="ItemCost" type="Double"/>
    <property name="TimeStamp" column="TimeStamp" type="DateTime"/>
</class>
  <class name="SnapShotItem" table="PID_SnapshotItems">
    <id name="ItemID">
      <generator class="assigned"/>
    </id>
    <version name="Version" unsaved-value="0"/>
    <many-to-one name="SnapShotID" class="SnapShotLocation" column="SnapShotID"/>
    <property name="ItemQuantity" column="Quantity" type="double"/>
    <property name="CountDate" column="InvCountDate" type="DateTime"/>
    <property name="CountAmount" column="InvCountQuantity" type="Double"/>
    <property name="ItemCost" type="Double"/>
    <property name="Timestamp" type="DateTime"/>
  </class>
<class name="SnapShotLocation" table="PID_SnapshotLocation">
    <id name="SnapShotID">
      <generator class="native"/>
    </id>
    <version name="Version" unsaved-value="0"/>
    <property name="LocationID"/>
    <property name="SnapShotDate" type="DateTime"/>
    <bag name="Items" inverse="true" cascade="all" optimistic-lock="false">
      <key>
        <column name="SnapShotID"/>
      </key>
      <one-to-many class="SnapShotItem"/>
    </bag>
  </class>
[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 20, 2007 9:20 am 
Beginner
Beginner

Joined: Thu Nov 02, 2006 5:11 pm
Posts: 32
Location: Toronto
Section 15.6. Batch updates describes how to configure Nhibernate for batch updates, given certain limitations. However, as a previous poster suggested, NHibernate isn't really designed for this use case. Updating 20000 records at a time is often better handled by native SQL constructs - you may want to consider using a stored procedure.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.