Changeset 7132


Ignore:
Timestamp:
Apr 21, 2016, 1:13:30 PM (7 years ago)
Author:
Nicklas Nordborg
Message:

References #2002: Change history logging should use batch API instead of Hibernate

The LogControl class now uses a PreparedStatement with SQL from the configuration files. The large test case from #2000 seems to be improved by 1-2 minutes.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/config/dist/mysql-queries.xml

    r7121 r7132  
    6262  </query>
    6363 
     64  <query id="DBLOG_INSERT_INTO_CHANGEHISTORYDETAILS" type="SQL">
     65    <sql>
     66      INSERT INTO [ChangeHistoryDetails]
     67        ([version], [history_id], [change_type], [item_id], [item_type], [change_info], [old_value], [new_value])
     68      VALUES (0, ?, ?, ?, ?, ?, ?, ?)
     69    </sql>
     70    <description>
     71      SQL query for inserting rows into the ChangeHistoryDetails table.
     72      The primary key (id) must be auto-generated.
     73      Parameters: history_id, change_type, item_id, item_type, change_info, old_value, new_value
     74    </description>
     75  </query>
    6476
    6577
  • trunk/src/core/common-queries.xml

    r7121 r7132  
    28322832    </description>
    28332833  </query>
     2834  <query id="DBLOG_INSERT_INTO_CHANGEHISTORYDETAILS" type="SQL">
     2835    <sql>
     2836      INSERT INTO [ChangeHistoryDetails]
     2837        ([id], [version], [history_id], [change_type], [item_id], [item_type], [change_info], [old_value], [new_value])
     2838      VALUES (nextval('hibernate_sequence'), 0, ?, ?, ?, ?, ?, ?, ?)
     2839    </sql>
     2840    <description>
     2841      SQL query for inserting rows into the ChangeHistoryDetails table.
     2842      The primary key (id) must be auto-generated.
     2843      Parameters: history_id, change_type, item_id, item_type, change_info, old_value, new_value
     2844    </description>
     2845  </query>
    28342846  <query id="GET_GROUPS_WITH_NONHIDDENMEMBERS" type="HQL">
    28352847    <sql>
  • trunk/src/core/net/sf/basedb/core/LogControl.java

    r6080 r7132  
    2323
    2424import java.lang.ref.WeakReference;
     25import java.sql.Connection;
     26import java.sql.PreparedStatement;
     27import java.sql.SQLException;
    2528
    2629import net.sf.basedb.core.data.ChangeHistoryData;
     
    4245  private TransactionDetails transactionDetails;
    4346  private org.hibernate.StatelessSession session;
     47  // Used for batch inserting into the "ChangeHistoryDetails" table
     48  private PreparedStatement insertIntoDetails;
     49  private final int batchSize;
     50  private int batchCount;
    4451 
    4552  LogControl(DbControl dc)
    4653  {
    4754    this.dc = new WeakReference<DbControl>(dc);
     55    // Use a higher batch size here since we are dealing with small objects
     56    this.batchSize = Config.getInt("db.batch-size", 50) * 10;
    4857  }
    4958 
     
    7786  /**
    7887    Adds information about a modified entity to the change history
    79     table.   
     88    table. The details may not be sent to the database immediately but
     89    can be batched for more efficient use of resources.
     90   
    8091    @param detail A fully initialized ChangeHistoryDetailData object
    8192      including a link to {@link ChangeHistoryData} that has
     
    8495  public void log(ChangeHistoryDetailData detail)
    8596  {
    86     getSession().insert(detail);
     97    try
     98    {
     99      if (insertIntoDetails == null)
     100      {
     101        // Create the batcher with SQL from the
     102        // configuration files
     103        org.hibernate.dialect.Dialect dialect = HibernateUtil.getDialect();
     104        String sql = PredefinedQuery.getQueryString("DBLOG_INSERT_INTO_CHANGEHISTORYDETAILS");
     105        sql = sql.replace('[', dialect.openQuote()).replace(']', dialect.closeQuote());
     106        Connection c = HibernateUtil.getConnection(dc.get().getHibernateSession());
     107        insertIntoDetails = c.prepareStatement(sql);
     108      }
     109     
     110      insertIntoDetails.setInt(1, detail.getChangeHistory().getId());
     111      insertIntoDetails.setInt(2, detail.getChangeType());
     112      insertIntoDetails.setInt(3, detail.getItemId());
     113      insertIntoDetails.setInt(4, detail.getItemType());
     114      insertIntoDetails.setString(5, detail.getChangeInfo());
     115      insertIntoDetails.setString(6, detail.getOldValue());
     116      insertIntoDetails.setString(7, detail.getNewValue());
     117      insertIntoDetails.addBatch();
     118    }
     119    catch (SQLException ex)
     120    {
     121      throw new BaseException(ex);
     122    }
     123    if (++batchCount == batchSize)
     124    {
     125      flush();
     126    }
    87127  }
    88128 
     
    99139  {
    100140    return HibernateUtil.createQuery(getSession(), hql);
     141  }
     142 
     143  /**
     144    Flushes any batched changes to the database.
     145  */
     146  public void flush()
     147  {
     148    if (batchCount > 0)
     149    {
     150      try
     151      {
     152        insertIntoDetails.executeBatch();
     153        batchCount = 0;
     154      }
     155      catch (SQLException ex)
     156      {
     157        throw new BaseException(ex);
     158      }
     159    }
    101160  }
    102161 
  • trunk/src/core/net/sf/basedb/core/log/LoggingInterceptor.java

    r7128 r7132  
    150150
    151151  /**
     152    Flush remaining changes in the log control.
     153   */
     154  @Override
     155  public void beforeTransactionCompletion(Transaction tx)
     156  {
     157    logControl.flush();
     158  }
     159
     160  /**
    152161    Signals successful commit or rollback to the log manager.
    153162    Note that this happens after the transaction/connection has been
Note: See TracChangeset for help on using the changeset viewer.