MyBatisの量産データ操作に関する体験

14986 ワード

MyBatisの量産データ操作に関する体験
 MyBatisの前身は有名なIbatisで、なぜかAppheを離れてMyBatisと改名しました. MyBatisはライト級のORMフレームと言っていますが、ネットでテストレポートを見たことがあります.ヒップホップに比べて利点があまり見えません.以下で面白い現象を説明します.MyBatisの公式文書によると、sql Sessionを獲得する時、大量更新のために準備されています.
session = sessionFactory.openSession();//    update

session = sessionFactory.openSession(ExecutorType.BATCH, true);//    update
 一般的には、MYSQLデータベースの一括操作時の速度は、それぞれの処理のための接続を確立するか、それともこれらの処理のための接続を確立するかに依存します.MyBatisのマニュアルによると、ExectorType.BATCHを選択するということは、取得したsql Sessionが一括して更新文を実行することを意味する.しかし、テストしてみましたが、1000個のデータを大量に挿入すると、ExectorType.BATCH方式の効率は普通の方式よりかなり悪いことが分かりました.テスト用のMapperの中のinsertの配置は以下の通りで、for循環で1000枚の記録を挿入します.
 
 1<insert id="insert" parameterType="sdc.mybatis.test.Student"> 2    <!-- WARNING - @mbggenerated This element is automatically generated by 

 3        MyBatis Generator, do not modify. This element was generated on Mon May 09 

 4        11:09:37 CST 2011. --> 5    insert into student (id, name, sex,

 6    address, telephone, t_id

 7    )

 8    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR},

 9    #{sex,jdbcType=VARCHAR},

10    #{address,jdbcType=VARCHAR}, #{telephone,jdbcType=VARCHAR}, #{tId,jdbcType=INTEGER}

11    )

12</insert>
 
  
 原因が分かりません.MyBatisのロゴ4 jを配置しました.ログを確認したいです.ロゴ4 j.jarとcommons-loging.jarをダウンロードしてプロジェクトのクラスパスに配置し、コードパスの下にファイルlogs 4 j.propertiesを新規作成します.内容は以下の通りです. 
log4j.rootLogger=DEBUG, stdout


# SqlMap logging configuration...

log4j.logger.com.ibatis=DEBUG

log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG

log4j.logger.com.ibatis.sqlmap.engine.cache.CacheModel=DEBUG

log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientImpl=DEBUG

log4j.logger.com.ibatis.sqlmap.engine.builder.xml.SqlMapParser=DEBUG

log4j.logger.com.ibatis.common.util.StopWatch=DEBUG

log4j.logger.java.sql.Connection=DEBUG

log4j.logger.java.sql.Statement=DEBUG

log4j.logger.java.sql.PreparedStatement=DEBUG

log4j.logger.java.sql.ResultSet=DEBUG


# Console output...

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
 
 そして、普通のsql Sessionを再度テストしてみます.ログの内容には1000件のデータが挿入されていますが、新規に接続しただけで、最後にまた接続を閉じました.つまりMyBatisの中の普通のsql Sessionはすでに大量挿入に対してデフォルトでは一回の接続で完成されているようですが、ExectorType.BATCH方式は何を提供していますか?しかもこの方式は効率が悪いようです.あるいはExectorType.BATCH方式を使っていますか?
 
DEBUG [main] - Created connection 3502256.

DEBUG [main] - ooo Connection Opened

DEBUG [main] - ==>  Executing: insert into student ( name, sex, address, telephone, t_id ) values ( ?, ?, ?, ?, ? ) 

DEBUG [main] - ==> Parameters:   0(String), male(String), addr0(String), dd(String), 3(Integer)

DEBUG [main] - ==>  Executing: insert into student ( name, sex, address, telephone, t_id ) values ( ?, ?, ?, ?, ? ) 

DEBUG [main] - ==> Parameters:   1(String), male(String), 

...............

...............

DEBUG [main] - xxx Connection Closed

DEBUG [main] - Returned connection 3502256 to pool.
 
 
最後の点はデータベースの大量挿入時のsql文レベルの最適化についてです.特に二つの方式をテストしました.StudentMapperには二つのinsertモードが配置されています.最初の対応はinsert value 1、insert value 2、、、第二の対応はinsert valuesです.後者はやっぱり前者よりずっと早いですね.以下は2つのinsertモードとテスト結果対応図です.   
<!--    for        --><insert id="insert" parameterType="sdc.mybatis.test.Student">

    insert into student (id, name, sex,

    address, telephone, t_id

    )

    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR},

    #{sex,jdbcType=VARCHAR},

    #{address,jdbcType=VARCHAR}, #{telephone,jdbcType=VARCHAR}, #{tId,jdbcType=INTEGER}

    )

</insert><!--    1000 list  --><insert id="insertBatch">

    insert into student ( <include refid="Base_Column_List"/> ) 

    values 

    <foreach collection="list" item="item" index="index" separator=",">

        (null,#{item.name},#{item.sex},#{item.address},#{item.telephone},#{item.tId})

    </foreach></insert>