2017-05-12 12 views
1

저는 Fluent NHibernate를 사용하여 데이터를 SQL Server 데이터베이스로 가져옵니다. 쿼리와 커밋은 세션이 계속되면 더 오래 걸립니다.

나는

Fluently.Configure(nhibernateConfig_) 
    .Mappings(map_ => map_.AutoMappings.Add(AutoMap 
    .AssemblyOf<EntityMapping>(new AutomapConfiguration()) 
    .UseOverridesFromAssemblyOf<EntityMapping>() 
    .Conventions.AddFromAssemblyOf<EntityMapping>())); 

(완벽하게 일) 내 개체에 자동 매핑을 사용하고 내 입력을 처리로서, 각 쿼리 읽고,

public AttributeTranslation GetOrCreateAttributeTranslation(Attribute attribute_, string language_) 
{ 
    AttributeTranslation translation = _session 
     .QueryOver<AttributeTranslation>() 
     .And(trans_ => trans_.Attribute == attribute_) 
     .And(trans_ => trans_.Language == language_) 
     .SingleOrDefault(); 

    if (translation == null) { 
     translation = new AttributeTranslation() { 
      Language = language_, 
      Attribute = attribute_ 
     }; 
     Save(translation); 
    } 

    return translation; 
} 

불행하게도 데이터베이스에서 데이터를 얻을 수 QueryOver를 사용 커밋 된 각 트랜잭션은 세션이 진행됨에 따라 더 오래 걸립니다.

// Surrounded in several for loops that process the input 
using (ITransaction transaction = _repo.BeginTransaction()) { 
    Stopwatch transGetWatch = Stopwatch.StartNew(); 
    AttributeTranslation translation = _repo.GetOrCreateAttributeTranslation(attribute, lang.Key); 
    transGetWatch.Stop(); 
    translation.DisplayName = value; 
    _repo.Save(translation); 

    Stopwatch commitWatch = Stopwatch.StartNew(); 
    transaction.Commit(); 
    commitWatch.Stop(); 

    Console.Write("\rGetTrans[{0}] Commit[{1}]     ", 
     transGetWatch.ElapsedMilliseconds, 
     commitWatch.ElapsedMilliseconds); 
} 

ID 생성을 위해 HiLo로 전환하려고했지만 아무 소용이 없었습니다.

public class AttributeTranslationMapOverride : IAutoMappingOverride<AttributeTranslation> 
{ 
    public void Override(AutoMapping<AttributeTranslation> map_) 
    { 
     map_.Id(attr_ => attr_.Id).GeneratedBy.HiLo("attributeTranslationMaxLo"); 
    } 
} 

쿼리 및 커밋은 호출 당 약 3-4 밀리 초에서 시작하여 끝에 약 80-100의 어딘가에서 끝납니다.

필자는 전반적인 성능을 반드시 낮추지 않아도되며, 호출 당 처음 3-4ms에서 안정화되기를 바랍니다.

여기에 무슨 일이 일어날 수 있습니까?

+2

'의심의 색인'이 높음은 세션의 1 차 수준 캐시가 커질 것이며 아마도 영향을 미칠 것입니다. 진단 목적으로 안전한 간격으로 세션을 정리하고 효과를 측정하려 했습니까? –

+0

@DavidOsborne 안전 간격으로 생각하는 것이 무엇입니까?또는 세션을 치료하는 것이 안전 할 때를 어떻게 결정할 수 있습니까? 행마다 Excel 파일에서 데이터를 가져오고 있습니다. 각 행이 나올 때마다 각 행이 자체 업데이트 프로세스가 될 수 있습니다. –

+1

거의 [this] (/ q/2151198/1178314)의 거의 dup입니다. –

답변

2

ORM으로서, NHibernate는 일괄 작업에 적합하지 않으므로 발생하는 문제가 있습니다. 그러나 배치 작업을 위해 어쨌든 사용하는 데 도움이되는 몇 가지 기능이 있습니다.

suspected by David Osborne으로 데이터 가져 오기와 같은 일괄 작업에 ISession을 사용하면 세션 첫 번째 레벨 캐시가 너무 커질 수 있습니다.

솔루션의 수를 선택할 수 있습니다

  • 지우기 데이비드 오스본에 의해 제안 및 reference documentation에서 권장하는 세션 (ISession.Clear). 데이터의 각 행이 이전 행과 공통된 일부 데이터를 참조하지 않으면 모든 행이 제거 된 후에도 지워지지 않습니다. 50 또는 100 행마다이를 수행하면 세션 1 레벨 캐시가 커지는 성능에 너무 큰 영향을주지 않기에 충분합니다. 결과에 따라 조정하십시오.
  • 세션이 저렴합니다. 삭제하는 대신 삭제하고 새 것을 사용할 수 있습니다. (그러나 각 행에서 그렇게하지 않는 것은 완전히 무료는 아닙니다.)
  • stateless session (ISessionFactory.OpenStatelessSession())을 사용해보십시오. 일부 일괄 처리에 더 적합 할 수 있습니다.

주 :

현재 구현은 거래 당 하나의 엔티티를 저장하는 것 같다. 대신 동일한 클래스의 엔티티 집합을 저장하면 batching (SQL-Server 이상)의 이점을 활용하고 성능을 향상시킬 수 있습니다. 또한 기본적으로 각 트랜잭션 후에 SQL 연결이 해제되므로 연결 해제/재 취득 수를 줄일 수 있습니다.

+0

잠시 동안 세션을 끝내고 놀았는데 실제로 사용 사례에서 성능에 놀라운 일을합니다. 아직 다른 어떤 시점에서 필요로하는 "콜렉션을 무시"하기 때문에 상태가없는 세션이 정확할 지 확신 할 수 없습니다. 모든 정보를 제공해 주셔서 감사합니다! 지금 각 줄마다 세션을 지우고 있으며 번개처럼 빠르게 진행됩니다. –