简体   繁体   中英

Java Hibernate tips about update all table fields performance

I have a requirement like this.

protected Integer[] updateFullTable(final Class clazz){
    final ProjectionList projectionList=Projections.projectionList().add(Projections.property("id"),"id");
    final Criteria criteria=session.createCriteria(clazz)
    .add(Restrictions.eq("typeOfOperation",1))
    .add(Restrictions.eq("performUpdate",true));
    criteria.setProjection(projectionList);
    final List idsList=criteria.list();
    final Integer[]ids = transformObjectArrayIntoIntegerArray(idList);
    //NOW WE UPDATE THE ROWS IDS. 
    final Query query=session.createQuery("update "+clazz.getName()+" set activeRegister=true and updateTime=:updateTime where id in (:ids)")
    .setParameter("updateTime",new Date())
    .setParameterList("ids",ids);
    query.executeUpdate();          
    return transform;
}

As you guys can see I need to update all rows in a table sometime I query all the rows ids and later apply the update to those ids in a separate query but the tables has a lot of records sometimes takes between 30 seconds to 10 minutes depends of the table .

I have change this code to only one update like this.

final Query query=session.createQuery("update "+clazz.getName()+" set activeRegister=true and updateTime=:updateTime where typeOfOperation=1 and performUpdate=true");

And with that only query I avoid the first query but I cannot not longer return the affected Ids. But later the requirement was change a

final StringBuilder logRevert;

Parameter was added.

Which needs to store the updated ids to apply a direct reverse update into the DB if required.

But with my update i cannot get the Ids not longer. My question is how can I get or return the affected ids using a stored procedure or some workaround in the DB or hibernate I mean get the first behaviour with only one query or a enhanced code..

Any tip.

I have tried

  1. Using criteria
  2. Using HQL.
  3. Using namedQuery
  4. Using SqlQuery
  5. Not using transformer returning me a raw Object[]

But the times still are somehow high.

I want something like

query.executeUpdate();   // RETURNS THE COUNT OF THE AFFECTED ROWS

But I need the affected Ids......

Sorry if the question is simple.

UPDATE

With @dmitry-senkovich I could do it using rawSQL but not with hibernate a separated question was made here.

https://stackoverflow.com/questions/44641851/java-hibernate-org-hibernate-exception-sqlgrammarexception-could-not-extract-re

What about the following solution?

SET @ids = NULL;

UPDATE SOME_TABLE
SET activeRegister = true, updateTime = :updateTime
WHERE typeOfOperation = 1 and performUpdate = true
      AND (SELECT @ids := CONCAT_WS(',', id, @ids));

SELECT @ids;

如果录入是日期时间,你可以选择与选择所有受影响的记录ID

Date updateTime = new Date(); // time from update

select id from clazz.getName() where updateTime=:updateTime and  activeRegister=true and typeOfOperation=1 and performUpdate=true

Updating a large number of rows in a table is a slow operation. This is due to needing to capture the 'old' value of each row in case of a ROLLBACK (due to explicit ROLLBACK , failure of the UPDATE , failure or subsequent query in same transaction, or power failure before UPDATE finishes).

The usual fix is to rethink the application design that necessitated the large UPDATE .

On there other hand, there is a possible fix to the schema. Please provide SHOW CREATE TABLE so I don't have to do as much 'hand waving' in the following paragraph...

It might be better to move the column(s) that need to be updated into a separate, parallel, table ("vertical partitioning"). This might be beneficial if

  • The original table has lots of wide columns ( TEXT , BLOB , etc) -- by not having to make bulky copies.
  • The original table is being updated simultaneously -- by the updates not blocking each other.
  • There are SELECT hitting the non-updated columns -- by avoiding certain other blockings.

You can still get the original set of columns -- by JOINing the two tables together.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM