2010-12-30 2 views
8

에 전달하려면 C# ...을 통해 스프레드 시트 파일을 읽고 스프레드 시트에 1000 개가 넘는 행이 있습니다. 저장 프로 시저에 데이터의 각 행을 보내야 일부 데이터베이스 측 로직을 수행하고 레코드를 업데이트해야합니다. 하나의 왕복 여행에서 1000 줄의 데이터를 모두 보내 시간을 절약하려면 도움이 필요합니다. 이 기술로 1000 개의 모든 행을 그룹화해야합니다.데이터의 대량 행을 저장 프로 시저

+0

SQL Server를 사용하고 있습니까? 그렇다면 어떤 버전의 SQL Server를 사용하고 있습니까? –

+1

1000은 그리 많지 않습니다. 걱정해야합니까? 한 번에 하나씩 1000 개의 행이 눈에 띄는 성능 문제를 일으키지 않을 수도 있습니다. 한 번에 하나씩하는 것이 더 쉽다면 먼저 시도해보고 무슨 일이 일어나는 지 봅니다. –

답변

20

SQL Server 2008 이상을 사용하고 있다고 생각하면 몇 가지 옵션이 있습니다. 이러한 모든 옵션은 뉴 올리언스의 Tech-Ed 2010 및 video of the session is available online에서 자세히 다루었습니다. 다음은 제시된 옵션의 요약입니다.

옵션 # 1 - (정말 video에 포함되지 않은) 대량 삽입 그냥 테이블에 데이터를 "덤프"필요하고 많은 일을 할 필요가없는 경우

이 최고의 선택이 될 것입니다 데이터를 데이터베이스로 가져 오는 것을 제외하고는 이것은 SqlBulkCopy 개체를 사용하는 ADO.NET에서도 지원됩니다.

는 모든 데이터를 가지고 큰 문자열을 구축하고 전체 문자열을 전달 구분 된 목록을 통과 - 나는 또한 쉽게

옵션 # 2 lightweight wrapper you can find on CodePlex은 SQL Server 및 ADO.NET 작업을하기 위해 작성한 저장 프로 시저로 변환합니다. 이것은 놀라 울 정도로 빠르지 만 많은 수하물이 함께합니다. 데이터를 가져오고 SQL-CLR로 분할하는 데 필요한 최상의 성능을 얻으려면 분할 기능이 있어야하며 데이터베이스를 소유하지 않은 경우 showstopper가 될 수 있습니다.

옵션 # 3 - XML ​​다시 한 번 하나 개의 매개 변수에 거대한 문자열을 전달하기 때문에이 옵션 # 2와 거의 동일

로 전달합니다. 또한 합리적인 성능을 지니고 있지만 옵션 # 2와 같은 수하물이 있지만 SQL Server가 XML을 구문 분석하는 방법을 알고 있기 때문에 분할 기능이 필요하지 않습니다.

옵션 # 4 - 테이블 반환 함수 (SQL 서버 2008)

이 옵션은 매우 멋진 최고의 성능을 제공을 사용합니다. 먼저 "테이블"형식의 SQL Server에서 값 형식을 만든 다음 해당 값 형식을 매개 변수로 사용하는 저장 프로 시저를 만듭니다. C#에서는 이제 SqlCommand를 만들고 SqlDbType.Structured 유형의 매개 변수를 추가 할 수 있습니다.

cmd.CommandType = CommandType.StoredProcedure; 
cmd.CommandText = "Test.spTVP"; 
var p = cmd.Parameters.Add("@Values", SqlDbType.Structured); 
p.TypeName = "Test.OrderTableType"; 
p.Value = dataTable; 
cmd.Execute…; 

저장 프로 시저가 실행될 때 모든 데이터가 저장 프로 시저의 테이블 변수에서 사용 가능합니다. 다른 테이블 변수와 마찬가지로 사용할 수 있으므로 데이터를 이동하는 것은 매우 간단합니다.

옵션 # 5 - 당신이 설정에 반복자를 가지고 있지만 때문에 다음 옵션 # 4 당신이 중 어떤 미친 성능을 얻을 스트리밍 테이블 반환 함수 (SQL 서버 2008)

조금 더 작업을 사용하여 저장 프로 시저로 전달하기 전에 클라이언트의 모든 데이터를로드 할 필요가 없기 때문입니다. .NET 런타임은 실제로 데이터를 데이터베이스로 스트리밍하고 저장 프로 시저의 구현은 동일합니다.

class MyStreamingTvp : IEnumerable<SqlDataRecord> { … 
} 
… 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.CommandText = "Test.spTVP"; 
var p = cmd.Parameters.Add("@Values", SqlDbType.Structured); 
p.TypeName = "Test.OrderTableType"; 
p.Value = new MyStreamingTvp(…); 
cmd.Execute…; 

이러한 모든 옵션

은 훌륭한 세부 사항 및 내가 처음에 언급 한 video에 약간의 유머로 덮여있다. 올해 Tech-Ed에서 제가 가장 좋아하는 세션 중 하나였습니다.

+0

+1 : 아주 좋은 옵션, 더 투표 할 수 있기를 바랍니다. – TalentTuner

+0

@Saurabh 나는 당신을 위해 그것을했습니다 :-) –

+0

안녕하세요, Ryan, 아주 좋은 답변입니다! 그냥 비디오 링크가 더 이상 작동하지 않습니다.새 링크를 올리시겠습니까? 아니면 여전히 세션 제목을 알고 있습니까? 세션 비디오는 여전히 cannel9에 있어야합니다 ... – Markus

3

라이언의 대답은 매우 철저하며 다양한 옵션을 다룹니다. 상대적으로 적은 수의 행 (1000-5000은 고려해야 할 모든 것이 아주 작음)의 경우 옵션 3으로 설명 된 것을 사용하여 XML을 저장 프로 시저 매개 변수로 전달합니다. 우리는 수시로 내 상점에서이 코드를 사용합니다.

스프레드 시트 데이터가 단순하고 이미 작성한 목록과 같은 코드로 쉽게 사용할 수 있다고 가정합니다. DataTable. 이 간단한 예제에서는 데이터를 단순화하기 위해 DataTable이라고 가정합니다.

I, 라이언처럼, 또한 SQL 2008

1 가정입니다 - 저장 프로 시저로 전달됩니다 XML로 데이터를 변환하여 C#에서 데이터를 준비합니다. 이것은 단지 XML 문자열입니다. 우리는 Base Data 클래스에서 메서드를 사용합니다. DataTable을 전달하면 저장 프로 시저에 매개 변수로 전달할 수있는 간단한 XML 문자열로 변환됩니다.

public string ConvertToXMLDataString(DataTable table) { 
     StringBuilder XMLString = new StringBuilder(); 
     if (string.IsNullOrEmpty(table.TableName)) 
      table.TableName = "DataTable"; 
     XMLString.AppendFormat("<{0}>", table.TableName); 
     DataColumnCollection tableColumns = table.Columns; 
     foreach (DataRow row in table.Rows) { 
      XMLString.AppendFormat("<RowData>"); 
      foreach (DataColumn column in tableColumns) { 
       XMLString.AppendFormat("<{1}>{0}</{1}>", row[column].ToString(), column.ColumnName); 
      } 
      XMLString.AppendFormat("</RowData>"); 
     } 
     XMLString.AppendFormat("</{0}>", table.TableName); 
     return XMLString.ToString(); 
    } 

2 - 나는 1000 데이터 행, 모든 정수, 10 열

를 포함하는 간단한 예제의 DataTable을 만들었습니다
DataTable table = new DataTable("DataTable"); 
      for(int i = 1; i < 11; i++){ 
       table.Columns.Add(new DataColumn("Column" + i.ToString())); 
      } 
      int j = 0; 
      for (int i = 0; i < 1000; i++) { 
       DataRow newRow = table.NewRow(); 
       for (int k = 0; k < table.Columns.Count; k++) { 
        newRow[k] = j++; 
       }    
       table.Rows.Add(newRow); 
      } 

ConvertToXMLDataString에 DataTable을 전달의 최종 결과는 잘 포맷 저장 프로 시저에 전달하고 쉽게 중에서 선택할 수 있습니다 DataTable에의 XML 표현 :

<DataTable> 
    <RowData> 
     <Column1>0</Column1> 
     <Column2>1</Column2> 
     <Column3>2</Column3> 
     <Column4>3</Column4> 
     <Column5>4</Column5> 
     <Column6>5</Column6> 
     <Column7>6</Column7> 
     <Column8>7</Column8> 
     <Column9>8</Column9> 
     <Column10>9</Column10> 
    </RowData> 
    <RowData> 
     <Column1>10</Column1> 
     <Column2>11</Column2> 
     <Column3>12</Column3> 
     <Column4>13</Column4> 
     <Column5>14</Column5> 
     <Column6>15</Column6> 
     <Column7>16</Column7> 
     <Column8>17</Column8> 
     <Column9>18</Column9> 
     <Column10>19</Column10> 
    </RowData> 
</DataTable> 

3 - 자, 처리 할 저장 프로 시저를 만들 X ML 데이터 문자열이 전달되었습니다.

CREATE PROCEDURE [dbo].[pr_Test_ConvertTable] 
@TableData XML 
AS 
BEGIN 
    SET NOCOUNT ON 
    SET ANSI_NULLS ON 
    SET ARITHABORT ON 

    DECLARE @TempTable TABLE (
     Column1 int, Column2 int, Column3 int, Column4 int, Column5 int, 
     Column6 int, Column7 int, Column8 int, Column9 int, Column10 int 
    ) 

    INSERT INTO @TempTable (Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10) 
    SELECT XmlTable.Data.value('(./Column1)[1]','int'), XmlTable.Data.value('(./Column2)[1]','int'), 
    XmlTable.Data.value('(./Column3)[1]','int'), XmlTable.Data.value('(./Column4)[1]','int'), 
    XmlTable.Data.value('(./Column5)[1]','int'), XmlTable.Data.value('(./Column6)[1]','int'), 
    XmlTable.Data.value('(./Column7)[1]','int'), XmlTable.Data.value('(./Column8)[1]','int'), 
    XmlTable.Data.value('(./Column9)[1]','int'), XmlTable.Data.value('(./Column10)[1]','int') 
    FROM @TableData.nodes('//DataTable/RowData') AS XmlTable(Data) 

    SELECT * FROM @TempTable 
END 
GO 

4 - 절차는 @TableData의 XML 변수를 받아 @TempTable라는 새로 만든 테이블 변수에 삽입합니다.

마지막 단계는 적절한 XML 매개 변수로 데이터베이스 호출을 작성하는 것입니다. 평소와 같이 SP를 호출하십시오. 매개 변수로 사용하십시오.

cmd.Parameters.Add("@TableData", SqlDbType.Xml).Value = ConvertToXMLDataString(table); 

여기 있습니다. 데이터를 적절히 조정하여 데이터를 처리 할 수 ​​있어야합니다. 필자는 일반적으로 DataTable을 전달하는 것을 싫어합니다. Object 또는 List를 전달하는 것이 좋지만이 경우 DataTable에 이미 데이터가있을 수 있습니다.

한 번 완료되었거나 자주 발생하지 않는 유형의 경우 XML 사용의 편의성을 위해 수행 한 성과가 최소화됩니다. 많은 사용자가 자주 발생하는 경우보다 효율적인 방법을 사용하십시오.

+0

아, 그리고 절대로 절대로 SELECT *를하지 않습니다. 그건 절름발이입니다. 예제 만 있으면됩니다. 이러지마. –