2010-05-21 2 views
6

배치 업데이트를 수행하는 방법이 궁금합니다. SQL Server 2005를 사용하고 있습니다.일괄 업데이트를 수행하는 방법은 무엇입니까?

나는 sqlDataAdaptor를 보았지만 처음에는 select 문을 사용하고 데이터 집합을 채우고 데이터 집합을 변경해야하는 것처럼 보였습니다.

지금 linq을 사용하여 select를 수행하므로이 방법을 계속 사용하려고합니다. 그러나 엄청난 업데이트를하는 것은 너무 느립니다. 그래서 멀리 나는 (선택 부분에 대한)하지만 일괄 업데이 트를 다른 뭔가를 사용하여 SQL에 내 linq을 유지할 수 있습니까?

감사

편집

나는이 준비 테이블 방식에 관심이 있지만 명확하지 여전히 그것을하는 방법을 잘 모르겠습니다 더 빨리 내가 ​​방법을 이해하지 않기 때문에 얼마나 업데이트 부분이 작동합니다.

그렇다면이 방법과 동시 연결을 처리하는 방법을 누구에게 보여줄 수 있습니까? Edit2가

는 XML을 사용하여 대량 업데이트를하려고 노력에서 내 최신 시도, 그러나 그것은 많은 자원을 사용하고, 내 공유 호스팅이 통과하는 것을 허용하지 않습니다이었다. 그래서 저는 다른 방법이 필요합니다. 그래서 나는 스테이징 테이블을 들여다 보지 않을 것입니다.

using (TestDataContext db = new TestDataContext()) 
      { 
       UserTable[] testRecords = new UserTable[2]; 
       for (int count = 0; count < 2; count++) 
       { 
        UserTable testRecord = new UserTable(); 

        if (count == 1) 
        { 
         testRecord.CreateDate = new DateTime(2050, 5, 10); 
         testRecord.AnotherField = true; 
        } 
        else 
        { 
         testRecord.CreateDate = new DateTime(2015, 5, 10); 
         testRecord.AnotherField = false; 
        } 


        testRecords[count] = testRecord; 
       } 

       StringBuilder sBuilder = new StringBuilder(); 
       System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder); 
       XmlSerializer serializer = new XmlSerializer(typeof(UserTable[])); 
       serializer.Serialize(sWriter, testRecords);    

       using (SqlConnection con = new SqlConnection(connectionString)) 
       { 
        string sprocName = "spTEST_UpdateTEST_TEST"; 

        using (SqlCommand cmd = new SqlCommand(sprocName, con)) 
        { 
         cmd.CommandType = CommandType.StoredProcedure; 

         cmd.CommandType = System.Data.CommandType.StoredProcedure; 

         SqlParameter param1 = new SqlParameter("@UpdatedProdData", SqlDbType.VarChar, int.MaxValue); 
         param1.Value = sBuilder.Remove(0, 41).ToString(); 
         cmd.Parameters.Add(param1); 
         con.Open(); 
         int result = cmd.ExecuteNonQuery(); 
         con.Close(); 
        } 
       } 
      } 

@ Fredrik Johansson 나는 당신의 말의 의미가 확실하지 않습니다. 당신이 나에게 각 레코드에 대한 업데이트 성명서를 작성하기를 원하는 것처럼 보입니다. 업데이트를 1 ~ 50,000 개 이상 업데이트해야하므로 그럴 수 없습니다. 그 시점까지는 알 수 없습니다. 3

편집 그래서 지금 내 SP입니다. 동시 연결을 할 수 있어야한다고 생각하지만 확신하고 싶었습니다.

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE PROCEDURE [dbo].[sp_MassUpdate] 
@BatchNumber uniqueidentifier 
AS 
BEGIN 
    update Product 
    set ProductQty = 50 
    from Product prod 
    join StagingTbl stage on prod.ProductId = stage.ProductId 
    where stage.BatchNumber = @BatchNumber 

    DELETE FROM StagingTbl 
    WHERE BatchNumber = @BatchNumber 

END 
+0

댓글을 설명하거나 정당화 할 수 있습니까? LINQ-to-SQL 업데이트 성능 문제? –

+0

기본적으로이 문제가 발생합니다. 나는 500 레코드를 삽입하고 500 레코드를 업데이트하고 싶었다. 유효성 검사는 1 분 58 초가 걸리고 대량 복사로 삽입하는 데 2 ​​초가 걸렸으며 SQL에 linq를 사용하여 500 줄을 모두 업데이트하고 삽입하는 데 4 분이 걸렸습니다. 30,000 ~ 50,000 개 이상의 행을 업데이트해야 할 필요가 있기 때문에이 문제를 해결하고 싶습니다. 그러나 나는 선택과 조작을 수행하기 위해 linq에 SQL을 사용하고 싶지 않다. 객체로 작업하는 것이 더 쉽다. 그것이 모든 레코드를 조작해야하고 난 그냥 루프의 각 linq 개체의 값을 – chobo2

+0

추출 할 수 있다면 쉽게 될 것 같아요 그래서 그것은 어떻게 생겼는지 상관 없어, 그리고 무엇에 던져 이제까지 필요합니다. – chobo2

답변

1

익명으로 SqlBulkCopy를 사용하면 매우 빠릅니다 (속도 향상이 200x 이상인 것으로 나타남 - 1500 초에서 6 초). 그러나 DataTable 및 DataRows 클래스를 사용하여 SQlBulkCopy에 데이터를 제공 할 수 있습니다 (더 쉬워 보입니다). 이 방식으로 SqlBulkCopy를 사용하면 .NET 3.0 규격에도 불구하고 추가 이점이 있습니다 (Linq는 3.5에만 추가됨).
일부 샘플 코드의 경우 http://msdn.microsoft.com/en-us/library/ex21zs8x%28v=VS.100%29.aspx을 확인하십시오.

0

직접 표현식 트리로 작업해야하지만 수행 할 수 있습니다. 사실, 이미 당신을 위해 썼는데, 당신은 단지 소스를 다운로드 할 수 있습니다

Batch Updates and Deletes with LINQ to SQL

대안은 바로 DataContextExecuteMethodCallExecuteCommand 방법을 사용하여 저장 프로 시저 또는 임시 SQL 쿼리를 사용하는 것입니다 .

+0

이 대안을 설명해 주시겠습니까? 업데이트 부분이 SP 또는 ado.net에 있는지 상관하지 않습니다. 내가 신경 쓰는 점은 객체를 처리 할 수 ​​있도록 linq에서 SQL을 선택하고 조작해야한다는 것입니다. 내가 조작 한 후에 데이터베이스로 어떻게 업데이트되는지 상관하지 않습니다. – chobo2

+0

@ chobo2 : 설명 할 부분이 확실하지 않습니다. 서버에 저장 프로 시저로 완전히 업데이트 로직을 쓸 수 있다면, 그 SP를 Linq to SQL 디자이너 화면으로 드래그하여 실행하십시오. 수천 개의 레코드를 다르게 업데이트하려고한다면 레코드별로 도움이되지 않습니다. 이 프로세스를 가속화하는 유일한 방법은 테이블 반환 매개 변수를 사용하거나 스테이지 테이블에 대량 삽입하는 것입니다. 둘 중 어느 것도 Linq to SQL을 지원하지 않습니다. – Aaronaught

+0

이 스테이징 테이블은 어떻게 작동합니까? – chobo2

1

번개 빠른 SqlBulkCopy를 사용하십시오. linq 쿼리 결과를 열거하는 사용자 지정 IDataReader 구현이 필요합니다. 더 많은 정보와 잠재적으로 적합한 IDataReader 코드를 보려면 http://code.msdn.microsoft.com/LinqEntityDataReader을보십시오.

1

sqlDataAdapter를 사용하여 일괄 업데이트를 수행 할 수 있습니다. 데이터 집합을 채우는 방법이 중요하지 않습니다. L2SQL 또는 뭐든간에, 당신은 다른 방법을 사용하여 업데이트를 할 수 있습니다. 데이터 테이블의 데이터를 사용하여 실행할 쿼리를 정의하십시오.

여기의 키는 UpdateBatchSize입니다. dataadapter는 정의한 크기의 일괄 처리로 업데이트를 전송합니다. 어떤 숫자가 가장 효과적인지 보려면이 값으로 만료해야하지만 500-1000의 숫자가 가장 효과적입니다.SQL은 업데이트를 최적화하고 좀 더 빠르게 실행할 수 있습니다. 배치 업데이트를 수행 할 때 데이터 테이블의 행 소스를 업데이트 할 수 없습니다.

이 방법을 사용하여 10-100K의 업데이트를 수행하며 일반적으로 2 분 이내에 실행됩니다. 그것은 당신이 비록 업데이 트에 따라 달라집니다.

죄송합니다. 이것은 VB에서 제공됩니다.

Using da As New SqlDataAdapter 
     da.UpdateCommand = conn.CreateCommand 
     da.UpdateCommand.CommandTimeout = 300 

     da.AcceptChangesDuringUpdate = False 
     da.ContinueUpdateOnError = False 
     da.UpdateBatchSize = 1000 ‘Expirement for best preformance 
     da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 'Needed if UpdateBatchSize > 1 
     sql = "UPDATE YourTable" 
     sql += " SET YourField = @YourField" 
     sql += " WHERE ID = @ID" 
     da.UpdateCommand.CommandText = sql 
     da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 
     da.UpdateCommand.Parameters.Clear() 
     da.UpdateCommand.Parameters.Add("@YourField", SqlDbType.SmallDateTime).SourceColumn = "YourField" 
     da.UpdateCommand.Parameters.Add("@ID", SqlDbType.SmallDateTime).SourceColumn = "ID" 

     da.Update(ds.Tables("YourTable”) 
End Using 

또 다른 옵션은 임시 테이블에 대량 복사 한 다음 쿼리를 실행하여 기본 테이블을 업데이트하는 것입니다. 이것은 더 빠를 수도 있습니다.

0

다른 소스의 linq에서 데이터 테이블을 수동으로/프로그래밍 방식으로 채우는 경우에도 SqlDataAdapter를 사용하여 일괄 업데이트를 수행 할 수 있습니다.

데이터 테이블의 행에 수동으로 RowState을 수동으로 설정해야합니다. 이에 대해서는 dataRow.SetModified()을 사용하십시오.

관련 문제