2010-12-28 2 views
1

무비 스토어 웹 사이트 (ASP.NET, EF4, SQL Server 2008 사용)에 대한 설정을 시도하고 있습니다. 시나리오에서 "회원"저장소에 저장된 "영화"카탈로그를 가져오고 싶습니다. 로 ActorName, MovieTitle 및 CatalogNumber를 포함하는 텍스트 파일은 다음과 같습니다EF4 수천 개의 레코드 가져 오기/조회 - 성능이 악취가납니다!

배우, 영화, CatalogNumber
존 웨인, 트루 그릿, 4577-12 (각 레코드에 대한 반복)

이 데이터에 사용됩니다 액터와 영화를 조회하고 "MemberMovie"레코드를 만들고,이 테이블을 사용하여 100 개가 넘는 레코드를 가져 오면 수입 속도가 끔찍합니다 :

  • 배우 테이블 : 필드 = {ID, 이름, 등}
  • 영화 표 : 필드 = {ID, 제목, ActorID 등}
  • MemberMovie 테이블 : 필드 = {ID, CatalogNumber, MovieID 등} (파일이 성공적으로 업로드 한 후) 텍스트 파일은 다음과 같습니다에서 MemberMovie 테이블로 데이터를 가져올 수

내 방법 :

  1. 컨텍스트를 만듭니다.
  2. 파일의 각 행에 대해 Actor 테이블에서 아티스트를 찾습니다.
  3. 아티스트 테이블의 각 영화에 대해 일치하는 제목을 찾습니다.
  4. 일치하는 Movie가 발견되면 컨텍스트에 새 MemberMovie 레코드를 추가하고 ctx.SaveChanges()를 호출하십시오.

내 구현의 성능이 좋지 않습니다. 내 기대는이 파일을 업로드 한 후 몇 초 안에 수천 개의 레코드로 수행 할 수 있으며 브라우저에서 시간을 보내는 뭔가가 있다는 것입니다.

내 질문은 : 일괄 검색/삽입을 수행하는 가장 좋은 방법은 무엇입니까? 새로 만든 된 MemberMovie 대신 SaveChanges를 한 번만 호출해야합니까? 저장 프로 시저 같은 것을 사용하여 이것을 구현하는 것이 더 낫겠습니까?

while ((fline = file.ReadLine()) != null) 
{ 
    string [] token = fline.Split(separator); 

    string Actor = token[0]; 
    string Movie = token[1]; 
    string CatNumber = token[2]; 

    Actor found_actor = ctx.Actors.Where(a => a.Name.Equals(actor)).FirstOrDefault(); 

    if (found_actor == null) 
     continue; 

    Movie found_movie = found_actor.Movies.Where(s => s.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault(); 

    if (found_movie == null) 
     continue; 

    ctx.MemberMovies.AddObject(new MemberMovie() 
    { 
     MemberProfileID = profile_id, 
     CatalogNumber = CatNumber, 
     Movie = found_movie 
    }); 

    try 
    { 
     ctx.SaveChanges(); 
    } 
    catch 
    { 
    } 
} 

어떤 도움에 감사드립니다 :

내 루프의 조각은 약이 (간결성을 위해 편집)입니다!

감사합니다, 데니스

+0

EF는 이러한 종류의 작업에서 성능이 떨어집니다. EF는 대량 작업을 지원하지 않으므로 가져 오기, 마이그레이션 등은 느립니다. 먼저 테이블에 인덱스를 추가하고 DB에 대한 왕복 수를 줄이십시오. 예를 들어, John Wayne과 50 개의 레코드가있는 경우 Actor 테이블과 모든 관련 동영상을 50 번 쿼리합니다. 알고리즘을 다시 정의해야합니다. 필요한 모든 액터를 함께로드 할 수도 있습니다. 처리 시간은 단축되지만 실제 처리 및 메모리로드는 증가합니다. –

답변

1

첫째 : 얼마 전에 내가 1 일 이후에 호출 SaveChanges를 대한 답을 썼다

, n 또는 모든 행 :

When should I call SaveChanges() when creating 1000's of Entity Framework objects? (like during an import)

그것은이다 사실 1 행 이상이 지난 후에 SaveChanges를 호출하는 것이 좋지만 결국에는 그렇지 않습니다.둘째

:

당신은 영화에서 배우 테이블과 제목에 이름을 인덱스가 있는지 확인하십시오, 그것은 도움이 될 것입니다.

대신 :

Actor found_actor = ctx.Actors.Where(a => a.Name.Equals(actor)).FirstOrDefault();

당신이 선택할 수 있습니다 당신은 자신의 ID를 필요로하는 경우 또한 당신은, 전체 배우를 선택하지 않아야

int? found_actor_id = ctx.Actors.Where(a => a.Name.Equals(actor)).Select(a => a.ID).FirstOrDefault();

다음

Something.ActorID = found_actor_id;

전체 액터 엔티티가 필요하지 않고 특별히 색인과 결합 할 때 추가 조회가 필요하지 않으므로 속도가 빨라질 수 있습니다. 셋째

: 매우 큰 파일을 보내는 경우

, 여전히에서도 좋은 성능과 타임 아웃의 확률이있다. 별도의 스레드에서이 가져 오기를 실행하고 즉시 응답을 리턴해야합니다. 모든 가져 오기에 일종의 식별자를 부여하고 사용자가이 ID로 상태를 확인할 수 있도록 허용 할 수 있습니다.

+0

Lukasz - 자세한 답변을 주셔서 감사합니다. 시간을 내 주셔서 감사 드리며 다른 질문/답변에 대한 링크도 정말 좋은 정보를 가지고 있습니다. –

관련 문제