2012-03-30 19 views
13

Oracle 11gでNHibernate 3.2の操作insertの処理をスピードアップしたいと思います。 、MyClass.PropertyX:これを行うには、私は私のforeachループで...NHibernateを使用したバルク挿入操作の高速化

Session.Save(entity); 
Session.Flush(); 
Session.Clear(); 

を試みたが、セッション中に不足しているオブジェクトによって引き起こされた例外ました:

を遅延役割のコレクションを初期化に失敗しました

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> 
    <session-factory> 
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property> 
    <property name="connection.driver_class">NHibernate.Driver.OracleClientDriver</property> 
    <property name="connection.connection_string">xxx</property> 
    <property name="dialect">NHibernate.Dialect.Oracle10gDialect</property> 
    <property name="adonet.batch_size">50</property> 
    <property name="query.substitutions">true=1, false=0</property> 
    <property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property> 
    </session-factory> 
</hibernate-configuration> 
:なしセッションまたはセッションが

別の試みは、バッチサイズを設定することでした閉じられませんでした。

加えて、私は私のコードでSession.SetBatchSize(50)を設定AN次の例外だ:いいえバッチサイズは、バッチ処理が 無効になっている、セッションファクトリ用に定義されなかった

を。バッチ処理を有効にするには、adonet.batch_size = 1に設定します。

この例外がスローされる唯一の場所はNonBatchingBatcherなので、セッションに間違ったバッターがあるようです。

ここで何が間違っていますか? NHibernateでバッチインサートをスピードアップするにはどうすればいいですか?

+0

あなたの最初の例外は何ですか?また、ループ内で 'Flush' *を実行すると、何もバッチ処理されません。 –

+0

@Diego Mijelshonさんが例外メッセージ – deamon

+0

を追加しました@deamonはこれはマルチスレッドですか? – Newbie

答えて

1

なぜあなたはセッションをクリアしていますか?

私はあなたがループ内のセッションをクリアするべきではないと思います。変更がデータベースに書き込まれていることを確認するために、トランザクションを使用したいと思います。

擬似コード:

foreach (var i in allElements) 
{ 
    using (var tx = session.BeginTransaction()) 
    { 
     ... do what you have to do with the object 
     tx.Commit(); 
    } 
} 

物事をスピードアップするのを助けることができる他のものがあります - あなたが本当にループの中で何をしたいのかを定義する必要があります。

35

動作するはずです後、

var testObjects = CreateTestObjects(500000); 

var stopwatch = new Stopwatch(); 
stopwatch.Start(); 
using (IStatelessSession session = sessionFactory.OpenStatelessSession()) 
using (ITransaction transaction = session.BeginTransaction()) 
{ 
    foreach (var testObject in testObjects) 
     session.Insert(testObject); 
    transaction.Commit(); 
} 

stopwatch.Stop(); 
var time = stopwatch.Elapsed; 

参考:読みする価値があるhttp://nhibernate.info/blog/2008/10/30/bulk-data-operations-with-nhibernate-s-stateless-sessions.html

+1

+1どのように答える必要があります!私の時間を節約しました – user919426

+0

ステートレスセッションを使用した後でキャッシュをクリアする必要がありますか?ステートフルセッションは、ステートレスセッションによって加えられた変更を受け取りますか? –

4

上記のヒントはすべて非常に有効で非常に便利です。コレクションに追加したい:ログを無効にする。コンソールにSQLを表示すると、NHProfを使用したプロファイリング、NLogまたはlog4netを介してログに記録されたSQLの自動コメント付け、きれいな書式設定など、著しく遅くなります。私たちの場合は設定:

cfg.AutoCommentSql = false; 
cfg.LogFormattedSql = false; 

をわずか1秒に〜6秒から、当社の一括挿入時間を減少させました。したがって、ロギングは潜在的により重大な問題を解決するのに役立ちますが、それはそれ自身のパフォーマンスヒットを伴います!

0

私はOracleに関する質問を知っていますが、SQLサーバーではクラスマッピングを取得してSqlBulkInsertで使用するDataTableを生成するルーチンを作成する予定でしたが、誰かが既にこれを行ったことがわかりました。

https://kaylaniam.wordpress.com/2015/03/13/nhibernate-and-sqlbulkcopy/

これはおそらく、SQL Server上で一括挿入を行うための最速の方法です。

関連する問題