C\#Sqlserver 에 데 이 터 를 대량으로 삽입 하 는 세 가지 방식

이 편 에 서 는 Sqlserver 에 데 이 터 를 대량으로 삽입 하 는 것 을 설명 하 겠 습 니 다.
먼저 테스트 할 데이터베이스 와 표를 만 듭 니 다.데 이 터 를 더 빨리 삽입 할 수 있 도록 표 의 홈 키 는 GUID 를 사용 합 니 다.표 에 색인 을 만 들 지 않 았 습 니 다.GUID 는 반드시 자체 성장 보다 빠 를 것 입 니 다.GUID 알고리즘 을 만 드 는 데 걸 리 는 시간 은 데이터 시트 에서 기 록 된 ID 의 값 을 다시 조회 한 다음 에 1 연산 을 하 는 것 보다 적 을 것 입 니 다.색인 이 존재 할 경우 기록 을 삽입 할 때마다 색인 재 구축 을 하 는 것 은 성능 을 소모 하 는 일이 다.표 에 피 할 수 없 는 색인 이 존재 한다 면 색인 을 먼저 삭제 한 다음 에 대량으로 삽입 한 다음 에 색인 을 재 구축 하 는 방식 으로 효율 을 높 일 수 있 습 니 다.

create database CarSYS; 
go 
use CarSYS; 
go 
CREATE TABLE Product(
Id UNIQUEIDENTIFIER PRIMARY KEY,
NAME VARCHAR(50) NOT NULL,
Price DECIMAL(18,2) NOT NULL
)
우 리 는 SQL 발 을 통 해 원래 데 이 터 를 삽입 하 는데 다음 과 같은 세 가지 방식 을 흔히 볼 수 있다.
방식 1,1,1,1 삽입,성능 최 악,사용 권장 하지 않 습 니 다.

INSERT INTO Product(Id,Name,Price) VALUES(newid(),'  1 ',160);
INSERT INTO Product(Id,Name,Price) VALUES(newid(),'  2 ',260);
......
방식 2

INSERT INTO Product(Id,Name,Price) VALUES
(newid(),'  1 ',160)
,(newid(),'  2 ',260)
......
방 식 삼

INSERT INTO Product(Id,Name,Price)
 SELECT NEWID(),'  1 ',160 
 UNION ALL 
 SELECT NEWID(),'  2 ',180
 UNION ALL
...... 
 C\#에서 ADO.NET 을 통 해 대량 작업 을 실현 하 는 것 도 세 가지 방식 이 존재 한다.
방식 1:조목조목 삽입

  static void InsertOne()
  {
   Console.WriteLine("             ");
   Stopwatch sw = new Stopwatch();
   long totalRow = 1000000;

   using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using    Open Close   。
   {
    string sql = "INSERT INTO Product(Id,Name,Price) VALUES(newid(),@p,@d)";
    conn.Open();
    for (int i = 0; i < 1000000; i++)
    {
     using (SqlCommand cmd = new SqlCommand(sql, conn))
     {

      cmd.Parameters.AddWithValue("@p", "  " + i);
      cmd.Parameters.AddWithValue("@d", i);
      sw.Start();
      cmd.ExecuteNonQuery();

      Console.WriteLine(string.Format("  1   ,  :{0}", sw.ElapsedMilliseconds));
     }
     if (i == 1000)
     {
      sw.Stop();
      break;
     }
    }
   }
   Console.WriteLine(string.Format("  {0}   , 1000       {1}  ,         {2}  ,{3}  ", totalRow, sw.ElapsedMilliseconds,
 ((sw.ElapsedMilliseconds / 1000) * totalRow), GetMinute((sw.ElapsedMilliseconds / 1000 * totalRow))));
  }

실행 결 과 는 다음 과 같 습 니 다.

100 w 개의 기록 을 삽입 하 는 데 50 분 이 걸 릴 것 으로 예상 되 며,기록 을 삽입 할 때마다 약 3 밀리초 정도 걸 릴 것 으로 예상 된다.
방식 2:SqlBulk 사용

  #region    
  static void InsertTwo()
  {
   Console.WriteLine("  Bulk       ");
   Stopwatch sw = new Stopwatch();
   DataTable dt = GetTableSchema();

   using (SqlConnection conn = new SqlConnection(StrConnMsg))
   {
    SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
    bulkCopy.DestinationTableName = "Product";
    bulkCopy.BatchSize = dt.Rows.Count;
    conn.Open();
    sw.Start();

    for (int i = 0; i < totalRow;i++ )
    {
     DataRow dr = dt.NewRow();
     dr[0] = Guid.NewGuid();
     dr[1] = string.Format("  ", i);
     dr[2] = (decimal)i;
     dt.Rows.Add(dr);
    }
     if (dt != null && dt.Rows.Count != 0)
     {
      bulkCopy.WriteToServer(dt);
      sw.Stop();
     }
     Console.WriteLine(string.Format("  {0}      {1}  ,{2}  ", totalRow, sw.ElapsedMilliseconds, GetMinute(sw.ElapsedMilliseconds)));
   }
  }
  static DataTable GetTableSchema()
  {
   DataTable dt = new DataTable();
   dt.Columns.AddRange(new DataColumn[] { 
  new DataColumn("Id",typeof(Guid)), 
  new DataColumn("Name",typeof(string)), 
  new DataColumn("Price",typeof(decimal))});
   return dt;
  }
  #endregion

실행 결 과 는 다음 과 같 습 니 다.

100 w 개의 기록 을 삽입 한 지 겨우 8s 가 넘 었 는데,매우 빠 르 지 않 습 니까?
방식 3:TVP(표 값 매개 변수)를 사용 하여 데 이 터 를 삽입 합 니 다.
sqlserver 2008 부터 TVP 를 지원 합 니 다.캐 시 시트 ProductTemp 를 만 들 고 다음 SQL 을 실행 합 니 다.

CREATE TYPE ProductTemp AS TABLE(
Id UNIQUEIDENTIFIER PRIMARY KEY,
NAME VARCHAR(50) NOT NULL,
Price DECIMAL(18,2) NOT NULL
)
실행 이 완료 되면 데이터베이스 CarSYS 아래 에 캐 시 시트 ProductTemp 가 한 장 더 있 는 것 을 발견 할 수 있 습 니 다.

100 w 개의 기록 을 삽입 하 는 데 총 11 초가 걸 린 것 을 알 수 있다.
요약:빅 데이터 의 대량 삽입 방식 은 가능 한 한 사용 을 피하 고 방식 2 와 방식 3 은 모두 매우 효율 적 인 대량 삽입 데이터 방식 이다.모두 DataTable 을 구축 하 는 방식 으로 삽입 되 었 으 며,DataTable 은 메모리 에 존재 한 다 는 것 을 알 고 있 기 때문에 데이터 양 이 매우 많 고 메모리 에 한꺼번에 저장 할 수 없 을 정도 로 클 때 세그먼트 로 삽입 할 수 있 습 니 다.예 를 들 어 9 천만 개의 데 이 터 를 삽입 해 야 하 는데 9 단 으로 나 누 어 삽입 할 수 있 고 한 번 에 1 천만 개 를 삽입 할 수 있다.그리고 for 순환 에서 데이터 베 이 스 를 직접 조작 할 때 우 리 는 가능 한 한 피해 야 한다.모든 데이터 베 이 스 를 연결 하고 열 고 닫 는 데 시간 이 걸 립 니 다.C\#에 데이터베이스 연결 풀 이 존재 하지만 우리 가 using 또는 conn.close()를 사용 하여 연결 을 풀 때 데이터 베 이 스 를 진정 으로 닫 지 않 았 습 니 다.연결 을 휴면 과 유사 하 게 존재 하 게 만 들 었 을 뿐 다시 작업 할 때연결 탱크 에서 휴면 상태의 연결 을 찾 아 깨 우 면 병발 능력 을 효과적으로 향상 시 키 고 연결 손실 을 줄 일 수 있다.연결 탱크 의 연결 수 는 모두 설정 할 수 있 습 니 다.
원본 다운로드:https://pan.baidu.com/s/1slKrrLr
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기