Dapper ORMを使用してSQLite一括挿入のパフォーマンスを向上させる

.net dapper sqlite

質問

私はSQLiteを使用してSQLiteデータベースに数万行のバルクを挿入するデスクトップアプリケーションに取り組んでいます。バルクインサートのパフォーマンスを最適化するのを助けてください。現在、60メガバイト分のデータをデータベースに挿入するのに最大50秒かかります。

  • パフォーマンスを向上させるためにどのような接続文字列を使用できますか?バッファサイズを変更する必要がありますか?これは接続文字列パラメータを介して可能ですか?パフォーマンスを向上させるための他の接続文字列パラメータはありますか?私の現在の接続文字列は:

    データソース= Batch.db;バージョン= 3;プール= True;最大プールサイズ= 10;同期=オフ; FailIfMissing = True;ジャーナルモード=オフ;

  • Dapper ORMを使用しています。 (StackOverflowの人たちによって構築された)高速一括挿入Sqliteに、ネットではありますか?

  • System.Data.Sqliteを使用してSQLiteに挿入しています。パフォーマンスを向上させる特別なコンパイル済みバージョンのsqliteを入手するのはどうでしょうか? SQLiteの1つのバージョンは他のバージョンより優れていますか?現在、System.Data.SQLiteをhttp://sqlite.phxsoftware.comから使用しています。

  • 現在、私はそれらをより速くするためにトランザクション内にインサートをラッピングしています(これは良い改善をしました)。

  • 私は一度に1つのテーブルに17のテーブルに挿入しています。これを別のスレッドで並列化してこれを高速化できますか?

現在のパフォーマンス。これは典型的ですか?私は良くできますか?

  • 19,000列のテーブルに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秒で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にアップグレードされました。 (私が見ることのできるパフォーマンスに違いはなかった)

  • DbParameterにTypeを割り当てているわけではありませんが、どちらの方法でもパフォーマンスの差がないようです。

  • 読み込みに関しては、Dapperのパフォーマンスを改善できませんでした。


人気のある回答

現在、私はそれらをより速くするためにトランザクション内にインサートをラッピングしています(これは良い改善をしました)。

私が一括挿入速度で目にした最大の利益は、挿入物を小さな塊に分割することでした。チャンクのどれがプラットフォーム/スキーマ/ etcごとにどれほど変わるか、私は確信しています。私は私のテストの間にそれが1000ほど近いと信じていました。



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ