2017-02-08 10 views
1

私は約140万レコードのデータを持っていますが、それを挿入するのに3時間以上かかります。私はそれに問題を見つけるように見えることはできません。hiberateを使用して挿入クエリ時間を最適化する方法は?

私は、アイデンティティから配列に変わります。ちょっと改善しただけですが、挿入を完了するまでにかなりの時間がかかります。

私が使用しています:

  • Hibernateは5
  • 春4
  • MSSQL 2014
  • Wildfly 10

のApplicationContext-hibernate.xml

<tx:advice id="txAdvice"> 
     <!-- the transactional semantics... --> 
     <tx:attributes> 
      <tx:method name="*_TransNew" propagation="REQUIRES_NEW" /> 
      <tx:method name="*_NoTrans" propagation="NEVER" /> 

      <tx:method name="create*" propagation="REQUIRED" /> 
      <tx:method name="update*" propagation="REQUIRED" /> 
      <tx:method name="delete*" propagation="REQUIRED" /> 
      <tx:method name="add*" propagation="REQUIRED" /> 

      <tx:method name="generate*" propagation="REQUIRED" /> 
      <tx:method name="get*" propagation="REQUIRED" /> 
      <tx:method name="is*" propagation="REQUIRED" /> 

      <!-- other methods use the default transaction settings (see below) --> 
      <tx:method name="*" read-only="true" /> 
     </tx:attributes> 
    </tx:advice> 


    <!-- ensure that the above transactional advice runs for any execution of 
     an operation defined by the following --> 
    <aop:config> 
     <aop:pointcut id="demoServiceOperations" 
      expression="execution(* com.test.*.*.*(..))" /> 
     <aop:advisor advice-ref="txAdvice" pointcut-ref="demoServiceOperations" /> 
    </aop:config> 

<bean id="sessionFactory" 
     class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2012Dialect</prop> 
       <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop> 
       <prop key="hibernate.cache.use_second_level_cache">true</prop> 
       <prop key="hibernate.cache.use_query_cache">true</prop> 
       <prop key="hibernate.jdbc.batch_size">50</prop> 
       <prop key="hibernate.order_inserts">true</prop> 
       <prop key="hibernate.order_updates">true</prop> 

       <prop key="hibernate.c3p0.min_size">5</prop> 
       <prop key="hibernate.c3p0.max_size">20</prop> 
       <prop key="hibernate.c3p0.timeout">1800</prop> 
       <prop key="hibernate.c3p0.max_statements">50</prop> 


      </props> 
     </property>   
    </bean> 

Umts.hbm.xml:

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<!-- Generated Nov 22, 2016 11:36:21 AM by Hibernate Tools 5.2.0.Beta1 --> 
<hibernate-mapping> 
    <class name="com.test.domain.Umts" table="TBLDM_UMTS" schema="dbo" catalog="DEMO" optimistic-lock="version" dynamic-update="true"> 
     <id name="umtsId" type="java.lang.Integer"> 
      <column name="UMTS_ID" /> 
      <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator"> 
       <param name="optimizer">pooled-lo</param> 
       <param name="increment_size">1</param> 
       <param name="sequence_name">UMTS_SEQ</param> 
      </generator> 
     </id> 
     <property name="cid" type="java.lang.Integer"> 
      <column name="CI" not-null="true" /> 
     </property> 
     <property name="channelNo" type="java.lang.Integer"> 
      <column name="UARFCN" /> 
     </property> 
     <property name="signalStrength" type="java.lang.Double"> 
      <column name="EC_IO" precision="53" scale="0" /> 
     </property> 
     <property name="sc" type="java.lang.Integer"> 
      <column name="SC" /> 
     </property> 
     <property name="latitude" type="java.lang.Double"> 
      <column name="LATITUDE" precision="53" scale="0" /> 
     </property> 
     <property name="longitude" type="java.lang.Double"> 
      <column name="LONGITUDE" precision="53" scale="0" /> 
     </property> 
     <property name="mcc" type="java.lang.Integer"> 
      <column name="MCC" not-null="true" /> 
     </property> 
     <property name="mnc" type="java.lang.Integer"> 
      <column name="MNC" not-null="true" /> 
     </property> 
     <property name="recvDate" type="date"> 
      <column name="RECV_DATE" length="10" /> 
     </property> 
     <property name="recvTime" type="time"> 
      <column name="RECV_TIME" length="16" /> 
     </property> 
    </class> 
</hibernate-mapping> 

サービスクラス:

public void process(List<Umts> umtsList) 
{ 
    for (int i = 0; i < umtsList.size(); i = i + PropertiesUtil.MAX_COMMIT_COUNT) 
     { 
      int min = i; 
      int max = i + PropertiesUtil.MAX_COMMIT_COUNT; 

      if (max > umtsList.size()) 
      { 
       max = umtsList.size(); 
      } 

      createUmts_TransNew(umtsList.subList(min, max)); 
     } 
} 
    @Override 
     public void createUmts_TransNew(Collection list) 
     { 
      // TODO Auto-generated method stub 

      umtsDAO.saveAll(list); 
     } 

DAOクラス:

@Transactional 
    public void saveAll(Collection collection) 
    { 
     log.debug("** save all"); 
     try 
     { 
      if (collection != null && collection.size() > 0) 
      { 
       for (Object obj : collection) 
       { 
        sessionFactory.getCurrentSession().saveOrUpdate(obj);     
       } 
      } 
     } 
     catch (RuntimeException re) 
     { 
      log.error("** save all failed", re); 
      throw re; 
     } 
    } 

**を編集には、接続プールがここに役割を果たしていますか?意味は、接続プールはパフォーマンスに役立ちますか? jarファイルをwildfly 10またはアプリケーション自体に追加する必要がありますか?

+0

なぜJavaでですか?バッチインサートを使用できますか? –

+0

@ScaryWombatは私がバッチインサートをしたものではありませんか? – shadow

+0

http://viralpatel.net/blogs/batch-insert-in-java-jdbc/ –

答えて

0

まず、pooled-loの値を増やしてみます。これを1に設定するので、フェッチする必要があるすべてのIDは実際の値を取得するためにDBを呼び出す必要があるため、最適化/プーリングは行われません。増分サイズが大きい場合、hibernateは、エンティティごとのラウンドトリップなしで、新しいエンティティに使用するIDのブロックをプリフェッチ/予約します。

あなたが掲示したコードがどのように実行されているか分かりませんが、私はあなたがそれらを1つのスレッドに順番に挿入していると仮定しています。

  • 各スレッドは、リスト/キューからいくつかの項目を挿入して挿入するスレッドプールを使用します。
  • 1つのスレッドで1つのトランザクションに挿入されるアイテムは、設定された休止状態のバッチサイズと理想的に同じサイズで、往復を最小限に抑えます。
  • プール内のスレッドの数が接続プールのサイズと同じであることを確認して、接続を待機するときにワーカースレッドをブロックしないようにします。
  • 接続プールのサイズがサーバーの負荷に適していることを確認して、接続プール(例:HikariCP)を使用してください。ここが面白いですwriteup on connection pool size.
+0

増分サイズはdbのキャッシュ値に従うべきですか? – shadow

+0

MSSQLシーケンスのキャッシュ値によって、シーケンス値の量がメモリに保持され、Xの使用ごとにシステムテーブルに書き込まれる量だけが決定されます。シーケンスのキャッシュプロパティに関係なく、MSSQLはhibernateによって要求されたときにシーケンスを1だけインクリメントします。 内部シーケンスがDB上でどのように処理されるかを、休止状態にするのと同じであってはいけません。 –

+0

まだ失われています。値を変更しても、パフォーマンスは変わりません。また、Wildflow 10やアプリケーション自体にlibとしてHikariCPを追加する必要がありますか? – shadow

関連する問題