2010-08-11 2 views
1

나는 여러 XML 파일을 가지고 있으며 각 파일은 Linq를 XML로 구문 분석 한 다음 NHibernate와 예리한 아키텍처 저장소를 사용하여 유지하는 실제 루트 객체를 만드는 '루트 객체'의 데이터를 포함하고있다. 데이터 삽입을 최적화하기 시작했으며 약 1 시간 40 분 동안 30000 개의 개체를 데이터베이스에 추가 할 수있었습니다. 그러나 이것은 여전히 ​​너무 느립니다.NHibernate insert/lookup performance

IO가 필요한 데이터베이스에서 개체를 조회하는 것이 병 목이라고 생각합니다. 다시 사용할 수 있도록 개체를 찾아야합니다.

루트 객체는 여러 저자을 가지고 : 나는 평소하지 않을 형식화 된 아이디 (뭔가를 사용하여 큰 속도를 달성

public class Author : Entity 
    { 
public virtual Initials Initials { get; set; } 
     public virtual ForeName ForeName { get; set; } 
     public virtual LastName LastName { get; set; } 
    } 

:

public virtual IList<Author> Authors { get; set; } 

저자는이 구조를 가지고) :

public class LastName : EntityWithTypedId<string>, IHasAssignedId<string> 
    { 
     public LastName() 
     { 
     } 
     public LastName(string Id) 
     { 
      SetAssignedIdTo(Id); 
     } 
     public virtual void SetAssignedIdTo(string assignedId) 
     { 
      Id = assignedId; 
     } 
    } 

다음과 같이 조회합니다. (잠재적으로 생성) :

LastName LastName = LastNameRepository.Get(TLastName); 

         if (LastName == null) 
         { 
          LastName = LastNameRepository.Save(new LastName(TLastName)); 
          LastNameRepository.DbContext.CommitChanges(); 
         } 
         Author.LastName = LastName; 

나는이 같은 저자를 찾고 있어요 :

propertyValues = new Dictionary<string, object>();    
propertyValues.Add("Initials", Author.Initials); 
        propertyValues.Add("ForeName", Author.ForeName); 
        propertyValues.Add("LastName", Author.LastName); 
        Author TAuthor = AuthorRepository.FindOne(propertyValues); 

        if (TAuthor == null) 
        { 
         AuthorRepository.SaveOrUpdate(Author); 
         AuthorRepository.DbContext.CommitChanges(); 
         Root.Authors.Add(Author); 
        } 
        else 
        { 
         Root.Authors.Add(TAuthor); 
        } 

내가이 문제를 개선 할 수 있습니까? 조회를 수행하는 대신 저장 프로 시저/HQL/pure SQL/ICriteria를 사용해야합니까? 조회 속도를 높이고 IO를 줄이기 위해 어떤 형태의 캐싱을 사용할 수 있습니까? CommitChanges가 필요하거나 트랜잭션으로 모든 것을 래핑해야합니까?

나는 이미 10 개의 루트 개체마다 내 세션 등을 내뿜습니다.

모든 의견은 매우 환영받을 것입니다. 미리 감사드립니다.

행복을 빌며,

기독교

답변

1

솔직히 말해서 SA ​​/ NHibernate를 이런 식으로 사용해서는 안된다. XML에서 대량 데이터를 가져 오기 때문에 SSIS와 같은 ETL 도구가 더 나은 선택입니다. DB 서버의 수작업 프로세스조차도 더 잘 작동 할 것입니다. 1 단계, XML을 테이블에로드, 2 단계, UPSERT를 수행하십시오. 덧붙여서, SQL 2008은 UPSERT 작업을위한 MERGE 명령을 도입했습니다.

댄의 의견에 동의 할 것입니다. 이니셜, 이름 및 성을 별도의 엔터티로 처리해야합니까? 간단한 문자열로 처리하면 성능이 향상됩니다. 도메인 모델에서 엔티티 자체가 고유하다고 지정하는 것은 무엇입니까? http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/06/24/bulk-processing-with-nhibernate.aspx

배치가 선택에 대한 지미의 블로그의 제안은 꽤 많은 도움이 될 것입니다

당신이 정말로 SA/자 NHibernate를 계속해야하는 경우

이의 읽기 있습니다.한 번에 250 레코드의 배치를 처리하려는 경우 모든 SELECT를 단일 NH 명령으로 수행하고 모든 데이터를 처리 한 다음 모든 업데이트를 다른 단일 배치로 수행하십시오 (EntityWithTypedId 및 adonet.batch_size 구성 설정이 도움이 될 것입니다.)

마지막으로 "XML을 Linq을 사용하여 구문 분석하는 구문"과 관련하여 - 실제로이 작업을 수행하는 가장 좋은 방법입니까? 입력 파일의 크기를 감안할 때 XML 파일을 deserialize하는 방식을 알고 계십니까? 아직 충분한 명성을 얻지 못했기 때문에 이것을 설명하는 페이지에 링크를 게시하지 않겠습니다. 그러나 독자가 그것에 대해 읽고 싶다면 Google은 "XML을 파싱하지 않습니다"라고 설명하고 첫 번째 기사에서 설명 할 것입니다. 그것.

희망이 도움이됩니다. Jon

+0

xsd2code를 사용하여 종료되었습니다. xml에 dtd 정보가 포함되어 있으면 다음을 사용하십시오. BlaClassBlaClass = ((BlaClass) (serializer.Deserialize (System.Xml.XmlReader.Create (new XmlTextReader (filepath), new System.Xml.XmlReaderSettings() {ProhibitDtd = false }})))); – cs0815

0

내가 할 것이 첫 번째 것은 당신이 별도의 엔티티로 이니셜, 뒤따라야하고, 성 개체를 필요가 있다고 생각하지 않는 저자의 실체를 단순화합니다. 나는 일반 문자열을 사용하는 것이 더 효율적이라고 생각한다 :

public class Author : Entity 
{ 
    public virtual string Initials { get; set; } 
    public virtual string ForeName { get; set; } 
    public virtual string LastName { get; set; } 
} 
+0

감사합니다. 이것은 이름에 lookuptables를 사용하려고했을 때 남은 부분입니다. 실제 문자열이 아니라 기본 키로 사용되었습니다. 그런 다음 int를 조회하는 데 많은 시간이 걸린다는 것을 알게되었습니다. 따라서 메모리를 사용하여 삽입 효율성을 지불했습니다. – cs0815

관련 문제