2015-01-11 3 views
1

나는 C#에서 채우는 기본 키 제약 조건이있는 몇 개의 테이블을 가지고 있습니다.기본 키를 위반하지 않고 행을 삽입하는 가장 빠른 방법

기본 키를 위반하지 않고 행을 삽입하는 가장 빠른 방법은 무엇입니까?

문을 하나씩 실행하거나 일괄 처리를 실행하면 상당한 오버 헤드가 추가됩니까?

조건에 따라 특정 행을 업데이트해야하는 경우 저장 프로 시저를 사용하고 지점별로 호출하거나 병합을 사용하는 것이 더 낫지 않습니까?

1.

foreach(var point in points) 
{ 
    ... 
    sqlCommand.ExecuteNonQuery(@" 
    BEGIN TRY 
     INSERT INTO POINTS ... 
    END TRY 
    BEGIN CATCH 
     IF ERROR_NUMBER() <> 2627 
     BEGIN 
      THROW 
     END 
    END CATCH", con) 
} 

2.

foreach(var point in points) 
{ 
    ... 
    sqlCommand.ExecuteNonQuery(@" 
    IF NOT EXISTS (Select 1 from POINTS where ...) 
    INSERT INTO POINTS ...", con) 
} 

3.

StringBuilder sb = new StringBuilder(); 
sb.AppendLine("BEGIN TRAN"); 
foreach(var point in points) 
{ 
    sb.AppendLine("IF NOT EXISTS (Select 1 from POINTS where ...) INSERT INTO POINTS ...") 
} 
sb.AppendLine("COMMIT TRAN"); 
sqlCommand.ExecuteNonQuery(sb.ToString()); 

4.

StringBuilder sb = new StringBuilder(); 
sb.AppendLine(@" 
    BEGIN TRAN 
    DECLARE @POINTS TABLE (
    ... 
    ) 
"); 
foreach(var point in points) 
{ 
    sb.AppendLine("INSERT INTO @POINTS ...") 
} 
sb.AppendLine(@" 
    MERGE POINTS as T 
    USING @POINTS as S 
    ON T.KEY=S.KEY 
    WHEN OT MATCHED THEN 
    INSERT ... 
"); 
sb.AppendLine("COMMIT TRAN"); 
sqlCommand.ExecuteNonQuery(sb.ToString()); 

답변

6

당신의 PO하는 경우 int 컬렉션이 큰 경우 SqlBulkCopy을 사용하여 임시 테이블 (예 : #NEW_POINTS) 먼저. 이렇게하면 점 당 개별 INSERT 문을 실행하지 않아도됩니다.

그런 다음 단일 MERGE 또는 INSERT/UPDATE 조합을 실행하여 데이터를 실제 POINTS 테이블로 이동하십시오.

+0

가장 효율적인 방법입니다. 데이터베이스의 홀딩 테이블에 넣으면 모든 SQL 세트 기반 명령을 사용하여 라이브 테이블에 데이터를 마사지 할 수 있습니다. – dbugger

+0

그래서 #NEW_POINTS와 POINTS 테이블 간의 병합은 @POINTS 변수보다 잘 수행됩니까? 나는 병합이 하나의 행을 걸러 내기 때문에 임시 내부의 삽입 성능이 무시할 만하다고 생각했다. – adrianvlupu

+0

임시 테이블 #POINTS 또는 변수 @POINTS를 사용하든 관계없이 MERGE가 동일하게 수행 할 것으로 기대한다. 그러나 SqlBulkCopy를 사용하면 점을 개별적으로 INSERT하는 것보다 훨씬 빠릅니다 (foreach (var point in points) ...). – Max

관련 문제