source

NHibernate로 대량 삽입 작업 속도 향상

ittop 2023. 8. 10. 21:30
반응형

NHibernate로 대량 삽입 작업 속도 향상

벌크 속도를 높이고 싶습니다.insertOracle 11g에서 NHibernate 3.2를 사용한 운영.이를 위해 노력했습니다.

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

내 안에서foreach루프이지만 세션에서 누락된 개체로 인해 예외가 발생했습니다.

역할 컬렉션인 MyClass를 게으르게 초기화하지 못했습니다.속성 X, 세션 또는 세션이 닫히지 않았습니다.

또 다른 시도는 배치 크기를 설정하는 것이었습니다.

<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)내 코드에서 다음과 같은 예외가 발생했습니다.

세션 팩토리에 대해 정의된 배치 크기가 없습니다. 배치를 사용할 수 없습니다.donet.batch_size = 1을 설정하여 배치를 사용하도록 설정합니다.

이 예외가 발생하는 유일한 위치는 NonBatchingBatcher입니다. 그래서 제 세션에 잘못된 배처가 있는 것 같습니다.

여기서 뭐가 문제야?정적 세션을 사용하지 않고 NHibernate로 배치 삽입 속도를 높이려면 어떻게 해야 합니까?

다음이 효과가 있을 것입니다.

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

위의 모든 팁은 매우 유효하고 매우 유용합니다.컬렉션에 하나를 추가하려고 했습니다. 로깅을 사용하지 않도록 설정하십시오.콘솔에 SQL이 표시되면 NHProf를 사용한 프로파일링, 자동 주석 처리 및 NLog 또는 log4net을 통해 기록된 SQL의 예쁜 포맷과 마찬가지로 속도가 현저하게 느려집니다.이 경우 설정:

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

대량 삽입 시간을 ~6초에서 1초 이상으로 단축했습니다.따라서 벌목은 잠재적으로 더 심각한 문제를 해결하는 데 도움이 될 수 있지만, 그 자체로 성능이 크게 향상됩니다!

읽을 가치가 있는 두 번째 URL입니다.

세션을 삭제하는 이유는 무엇입니까?

루프에서 세션을 삭제하면 안 된다고 생각합니다.변경사항이 데이터베이스에 기록되도록 하려면 트랜잭션을 사용하는 것이 좋습니다.

의사 코드:

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

속도를 높이기 위해서는 루프에서 실제로 무엇을 하고 싶은지 정의해야 합니다.

Oracle에 대한 질문이었지만 SQL Server의 경우 클래스 매핑을 가져오고 SQLBulkInsert에서 사용할 DataTable을 생성하는 루틴을 작성하려고 했지만 이미 누군가가 이 작업을 수행했다는 것을 알게 되었습니다.

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

SQL Server에서 대량 삽입을 수행하는 가장 빠른 방법입니다.

아래 코드는 여러 개의 복합 엔티티를 삽입하는 데 사용됩니다.

 public static void SqlBulkInsert(this ISession session, DataTable dataTable, string tableName)
    {
        var conn = (SqlConnection)session.Connection;
        using (var cmd = new SqlCommand())
        {
            session.Transaction.Enlist(cmd);
            using (var copy = new SqlBulkCopy(conn, SqlBulkCopyOptions.FireTriggers, cmd.Transaction))
            {
                copy.BulkCopyTimeout = 10000;
                copy.DestinationTableName = tableName;
                foreach (DataColumn column in dataTable.Columns)
                {
                    copy.ColumnMappings.Add(column.ColumnName, column.ColumnName);
                }

                copy.WriteToServer(dataTable);
                copy.Close();
            }
        }
    }

유지할 복합 엔터티 개체에서 DataTable 개체를 채우는 메서드를 만들어야 합니다.

언급URL : https://stackoverflow.com/questions/9943967/speed-up-bulk-insert-operations-with-nhibernate

반응형