Dapper ORM을 사용하여 SQLite 대량 삽입의 성능 향상

.net dapper sqlite

문제

SQLite를 사용하여 SQLite 데이터베이스에 수만 행의 행을 삽입하는 데스크톱 응용 프로그램에서 작업하고 있습니다. 대량 삽입 성능을 최적화하는 데 도움을 드리고 싶습니다. 현재 데이터베이스에 60 메가의 데이터를 삽입하는 데 최대 50 초가 소요됩니다.

  • 성능 향상을 위해 어떤 연결 문자열 매개 변수를 사용할 수 있습니까? 버퍼 크기를 변경해야합니까? 연결 문자열 매개 변수를 통해 가능합니까? 성능 향상을위한 다른 연결 문자열 매개 변수가 있습니까? 내 현재 연결 문자열은 다음과 같습니다.

    데이터 원본 = Batch.db, 버전 = 3, 풀링 = True, 최대 풀 크기 = 10, 동기 = 꺼짐, FailIfMissing = True, 저널 모드 = 꺼짐,

  • Dapper ORM을 사용하고 있습니다. (StackOverflow에서 녀석들에 의해 지어졌다.) 대량의 Sqlite에 .net을 삽입하는 더 빠른 방법이 있습니까?

  • System.Data.Sqlite는 SQLite에 삽입하는 데 사용됩니다. 성능을 향상시키는 sqlite의 특수 컴파일 버전을 얻는 방법은 무엇입니까? SQLite의 한 버전이 다른 버전보다 나은가요? 현재 http://sqlite.phxsoftware.com 에서 System.Data.SQLite를 사용 중입니다 .

  • 현재, 나는 그들을 빨리 만들기 위해 트랜잭션 내부에 인서트를 포장하고 있습니다 (이것은 좋은 개선을 이루었습니다).

  • 한 번에 하나의 테이블에 17 개의 테이블을 삽입하고 있습니다. 이 스레드를 다른 스레드에서 병렬 처리하여 속도를 향상시킬 수 있습니까?

현재 성능. 이게 전형적인가요? 더 잘할 수 있을까요?

  • 19 개의 열이있는 55,000 개의 행 : 삽입 2.25 초 (24k 삽입 / 초)
  • 63 열을 가진 테이블에 10,000 행 : 삽입 2.74 초 (3.7k / 초)

나는 SQLite를 좋아하지만 조금 더 빨리 만들어주고 싶다. 현재 XML 직렬화를 사용하여 XML 파일에 내 개체를 저장하는 것이 SQLite 데이터베이스에 저장하는 것보다 빠르기 때문에 상사가 다음과 같은 질문을합니다. 왜 SQLite로 전환합니까? 아니면 MongoDB 나 다른 객체 데이터베이스를 사용해야합니까?

수락 된 답변

그래서 마침내 .NET을 사용하여 SQLite의 고성능 대량 삽입에 대한 트릭을 발견했습니다. 이 트릭은 인서트 성능을 4.1 배 향상 시켰습니다! 내 총 저장 시간은 27 초에서 6.6 초로 늘어났습니다. 와우!

이 기사에서는 SQLite에 대량 삽입을 수행 하는 가장 빠른 방법에 대해 설명합니다. 키는 동일한 매개 변수 오브젝트를 재사용하지만 각 레코드는 삽입하여 다른 값을 지정합니다. .NET이 모든 DbParameter 객체를 구성하는 데 걸리는 시간은 실제로 늘어납니다. 예를 들어, 100k 행과 30 열 = 300 만 개의 매개 변수 오브젝트가 작성되어야합니다. 대신, 단지 30 개의 매개 변수 객체를 생성하고 재사용하는 것이 훨씬 빠릅니다.

새로운 성능 :

  • 53,000 초 = 55,000 행 (19 열) = 100k 삽입 / 초

        internal const string PeakResultsInsert = @"INSERT INTO PeakResult values(@Id,@PeakID,@QuanPeakID,@ISTDRetentionTimeDiff)";
    
                var command = cnn.CreateCommand();
                command.CommandText = BatchConstants.PeakResultsInsert;
    
                string[] parameterNames = new[]
                                     {
                                       "@Id",
                                       "@PeakID",
                                       "@QuanPeakID",
                                       "@ISTDRetentionTimeDiff"
                                      };
    
                DbParameter[] parameters = parameterNames.Select(pn =>
                {
                    DbParameter parameter = command.CreateParameter();
                    parameter.ParameterName = pn;
                    command.Parameters.Add(parameter);
                    return parameter;
                }).ToArray();
    
                foreach (var peakResult in peakResults)
                {
                    parameters[0].Value = peakResult.Id;
                    parameters[1].Value = peakResult.PeakID;
                    parameters[2].Value = peakResult.QuanPeakID;
                    parameters[3].Value = peakResult.ISTDRetentionTimeDiff;
    
                    command.ExecuteNonQuery();
                }
    

그것은 큰 테이블에 삽입하기 위해 Dapper를 사용할 수 없다는 것을 끝냅니다. (내 작은 테이블을 위해, 나는 여전히 Dapper를 사용한다.)

내가 발견 한 몇 가지 다른 점에 유의하십시오.

  • 여러 스레드를 사용하여 동일한 데이터베이스에 데이터를 삽입하려고 시도했지만 어떤 개선도 이루어지지 않았습니다. (차이를 만들지 않았다)

  • System.Data.Sqlite 1.0.69에서 1.0.79로 업그레이드되었습니다. (나는 볼 수있는 성능에 차이를 만들지 않았다)

  • Type을 DbParameter에 할당하지 않을 경우 성능 차이가 발생하지 않습니다.

  • 읽기의 경우 Dapper의 성능을 향상시킬 수 없었습니다.


인기 답변

현재, 나는 그들을 빨리 만들기 위해 트랜잭션 내부에 인서트를 포장하고 있습니다 (이것은 좋은 개선을 이루었습니다).

대량 삽입 속도에서 가장 큰 이득은 삽입을 더 작은 조각으로 나누는 것이 었습니다. 청크의 크기는 플랫폼 / 스키마 / 등마다 다릅니다. 나는 내 시험 도중 1000 년 가까이 믿었습니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.