2011-12-29 3 views
3
내가 삽입 쿼리를 그룹화 및 배치의 크기를 구성 할 수 있습니다 일괄 데이터베이스로 보내 syabse 데이터베이스에 대량 삽입을하고있는 중이 야

이 코드는 배치 크기 대에 대한 관찰이 성능을 사용하여이배치 크기가 대량 삽입 성능에 미치는 영향은 무엇입니까?

public static void InsertModelValueInBulk(DataSet modelValueData, int clsaId) 
    { 
     int batchSize = Convert.ToInt32(ConfigurationManager.AppSettings["BatchSize"].ToString());    
     IList<string> queryBuffer = new List<string>();  
     using (var connection = GetAseConnection()) 
     { 
      connection.Open(); 
      var tran = connection.BeginTransaction(); 
      try 
      {     
       for (int i = 0; i < modelValueData.Tables[0].Rows.Count; i++) 
       { 

        var insertItem = string.Format(@"select '{0}',{1},{2},{3},'{4}','{5}','{6}',{7}", row["ModelValueID"], Convert.ToInt32(row["StockModelID"]), Convert.ToInt32(row["ModelItemID"]), 
                     fyeStr, row["Period"], value, row["UpdatedUser"], clsaId); 
        queryBuffer.Add(insertItem); 
        if (queryBuffer.Count % (batchSize) == 0 && queryBuffer.Count > 0) 
        { 
         var finalQuery = @"INSERT INTO InsertTable (ModelValueID, StockModelID, ModelItemID, FYE, Period, Value, UpdatedUser,id) 
     " + String.Join(" union ", queryBuffer.ToArray<string>());       

         using (var cmd = new AseCommand(finalQuery, connection, tran)) 
         {          
           cmd.ExecuteNonQuery();        
         } 
         queryBuffer.Clear(); 
        }      
       }     
       tran.Commit(); 
      } 
      catch 
      { 
       tran.Rollback(); 
       throw; 
      } 
      finally 
      { 
       tran.Dispose(); 
      } 
     } 
    } 

처럼 약간 보인다 20000을 삽입하는 데 걸린 시간은 J 곡선을 형성하는데, 샘플 데이터는 다소 비슷합니다

일괄 처리 크기 10 = 일괄 처리 크기가 50 => 20 초, 100 => 10 초, 200 => 20 일 때 작업이 완료됩니다 초, 500 30 초, 1000 => 1 분.

이 J 곡선의 원인은 무엇인지 이해하고 싶습니다. 앱 서버 메모리 또는 일부 데이터베이스 서버 설정 또는 그 밖의 다른 작업과 관련이 있습니까? 무엇이 100을 최적으로 만들고 이것이 더 조정될 수 있습니까?

+0

나는 거의 추측을하고 배치 크기가 커지면 아마도 일부 캐싱이 진행된다고 말할 수 있습니다. 또한 개폐 연결의 총 개수와 관련 될 수도 있습니다 ..당신은 새로운 커넥션을 생성하는 것과 정적 인 커넥션을 생성하여 테스트 할 수 있습니다. 또한 상당한 차이가 있습니다. – MethodMan

답변

1

나는

  1. 내가 할 수있는 모든 코드를 포장 것입니다 .. 당신 내가 커밋은 항상 성공적으로 될 것이라고 가정하지 것이다 커밋에 .. 예를 들어 .. 당신이 기존 코드와 함께 꽤 feww 문제를 참조하십시오 실패하거나 try catch 주위에서 폭발 할 가능성이 있습니다. Commits, Rollbacks cmd.Execute

  2. Select 문을보고 개인적으로 저장 프로 시저를 만들 것이고 그렇게 할 수 없다면 선택 문자열을 만들 것입니다. const.

  3. 나는 개인적으로 내 거래의 이름을 것입니다 ..하지만 .. 당신

  4. 이 라인은 모든 메소드 호출하는 동안 변화의 가능성을 가지고 최대

    INT BATCHSIZE = Convert.ToInt32 (ConfigurationManager가 있습니다. AppSettings [ "BatchSize"]. ToString()); 나는 그것을 정적 전화를하지 당신은 당신의 코드를 리팩토링

  5. 시도 방법에 갈 때마다 호출 할 수 없습니다 경우
    .. ..
+0

유효 포인트가 있습니다.하지만 이것은 기본 플로우를 보여주기 위해 코드의 버전에서 압착됩니다. –

+0

다음과 같이 변경할 수 있습니다. 당신은 당신이 물건을 구조화하는 방식을 바라 보는 SQL Injection에 자신을 노출시킬 수 있습니다. – MethodMan

3

BULK를 따라 혼란 조금 보이기 시작이야 insert는 배치 크기 동안 테이블을 잠급니다. 잠금 장치에는 기본적인 오버 헤드가 있으므로 작은 배치는 거의 이익을 얻지 못하지만 배치 작업 사이의 테이블에 대해 다른 작업을 수행하게하십시오.

큰 일괄 처리는 좋은 점입니다. 트랜잭션이므로 현재 배치가 완료 될 때까지 데이터가 커밋되지 않습니다. 이것은 로그 파일에 쓰는 것을 의미합니다. 실제로 대량의 일괄 처리는 로그를 증가시키고 IO 집중적으로 발생 시키므로 더 많은 로그가 사용됨에 따라 경합이 증가합니다.

그 라인을 따라 뭔가.

편집 : 다른 두 가지 1) 매개 변수화 된 입력 을 사용하십시오. 2) # 1을 수행하지 않으면 "공용체"가 고유를 생성합니다. "합집합 전체"사용

관련 문제