0

ADO.netの挿入を劇的に高速化するためにできることがあるかどうかを探していますが、それでも複数のINSERT INTO table values (...)コマンドで挿入を行います。独自のクエリ不可能なデータベース ファイルから SQL Server にデータをステージングしています。私が書いているユーティリティは、スクリプトから使用されます。

可能な限り最高のパフォーマンスを得るためにINSERT INTOは、間違ったルートを追求することを理解していますが、試してみるべきADO.netまたはSQL Serverのアプローチがあるかどうかを知りたいです。

C# 2010 を使用して SQL Server 2008 に接続しています。Native Client 10.0 で Microsoft の ODBC 3.5 ドライバーを使用して SQL Server にデータを挿入する非管理コードとパフォーマンスを比較しています。ODBC のパフォーマンスに匹敵できると期待するのは合理的ですか?

宛先テーブルにはインデックスやその他の制約、トリガーはなく、単なるステージング テーブルです。ソース データは、一連の非標準データ型であり、文字列に変換する必要があります。

関連する詳細に取り除かれると、私のコードは次のとおりです。

SqlCommand comm = new SqlCommand;
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
SqlTransaction insertTransaction = conn.BeginTransaction();
comm.Connection = conn;
comm.Transaction = insertTransaction;

while(buffer.ReadNext())  // fill a buffer that I use to make my query
{
    // form my insert statement and assign it
    // It looks like: INSERT INTO myTable VALUES (5,'2016-02-16',NULL,3)
    // A good fraction of the data is numeric with decimal points. A good
    // fraction is dates.  The parsing and string building,
// extravagantly inefficient as it is, is not the culprit.
    // The  INSERT INTO does not specify the column names

    comm.CommandText = myStatement;
    if (comm.ExecuteNonQuery() != 1) {throw...}
}

insertTransaction.commit;

さまざまな分離レベルを指定してみました。指定でき.Snapshotませんでした (それを許可するようにターゲット データベースを構成したくありません)。何も大きな違いはありませんでした。

INSERT ステートメントを形成するだけでスピンできるようにコメントアウトするcomm.ExecuteNoQueryと、実際に何かを実行している場合に必要と思われる速度で実行されます。コメントを外すと、思ったよりも約 8 倍の時間がかかります。「『8倍』はどこから?」あなたが尋ねる。さて、私は Pervasive Data Integrator (ye olde Data Junction) で同様の操作 (エンド ツー エンドの同一操作) を行います。Pervasive がクラッシュしたときの診断から、私とINSERT INTO 同じように、プログラムが連続したステートメントを使用して挿入を行っていると思われます。INSERT INTO私のプログラムよりも約 8 倍速くなり、実行しない場合にステートメントを 作成するよりもわずかに遅くなります。

Pervasive Integrator は ODBC を介して追加しており、ODBC ドライバーは Sql Native クライアントを使用するように設定されています。また、Data Integrator は .Net ソフトウェアではありません。私は実際にODBCを試したことはありません.ODBCを試してみることにします.

一括挿入を行う目的で dataTable を入力しようとしましたが、データセットの入力にも時間がかかりすぎました。一括挿入を使用する別の方法がそれを機能させるための最も速い方法であると思いますが、最終的に私のアプローチの使用をやめたとしても、INSERT INTOなぜそんなに時間がかかるのか不思議です(私が思っているよりも)

挿入ステートメントはかなり長く、テーブルには約 350 列あります。

4

2 に答える 2

1

挿入値を簡単なものにグループ化してみましたか:

INSERT INTO myTables VALUES (5,'2016-02-16',NULL,3), (6,'2015-02-16',NULL,6), (7,'2012-02-16',NULL,6)...

これは単純な実装ですが、エレガントではありません(テストされておらず、メモ帳に書いたので、タイプミスの可能性が高いです)が...

SqlCommand comm = new SqlCommand;
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
SqlTransaction insertTransaction = conn.BeginTransaction();
comm.Connection = conn;
comm.Transaction = insertTransaction;

String baseQuery = "INSERT INTO myTable VALUES ";

List<String> values = new List<String>();

Int32 i = 0;

while(buffer.ReadNext())  // fill a buffer that I use to make my query
{
    // Build your VALUES section here
    values.Add("(5,'2016-02-16',NULL,3)");

    if (i % 100 == 0)  // Chunk these every 100
    {
        myStatement = baseQuery + String.Join(", ", values.ToArray());

        comm.CommandText = myStatement;

        if (comm.ExecuteNonQuery() != 1) {throw...}

        insertTransaction.commit;

        values = new List<String>();  // Clear out our values and start a new
    }

    i++;
}

if (values.Count > 0)  // If any are left, INSERT them
{
    myStatement = baseQuery + String.Join(", ", values.ToArray());

    comm.CommandText = myStatement;

   if (comm.ExecuteNonQuery() != 1) {throw...}

   insertTransaction.commit;
}
于 2012-03-13T16:32:12.960 に答える
0
  1. データは一度に 1 行で取得されますか? つまり、ユーザーがデータをアプリケーションに入力し、ボタンを押して挿入を開始するようにしますか?
    また
  2. すべてのデータはすぐに挿入できますか?

(1.) 場合は、これまで行ってきた方法で INSERT INTO を実行します。

私は、アプリケーション/クライアント側で一度に 1 行ずつデータを蓄積することに反対しています。これは多くの問題につながります。

(2.) の場合、一括インポートを行います。

一括インポートと一括エクスポートの操作には 3 種類あります
http://msdn.microsoft.com/en-us/library/ms187042.aspx

これらのファイルはテキスト形式ですか?
それらは柱状ですか?
それらはファイル システム (つまり、C:\pathTo\file.ext) からアクセスできますか?
はいの場合は、bcp 形式のファイルを生成します (C:\pathTo\file.ext を含めるように注意して、プログラムから出力します)。
次に、ステージング テーブルを TRUNCATE (または上記で生成されたフォーマット ファイルの TRUNCATE INTO) し、フォーマット ファイルとデータベース接続をパラメーターとして指定して、system() 呼び出しを介して bcp ユーティリティを呼び出します。
超高速です。
直接 bcp アップロードは、ado.net 経由でアップロードできるものより優れています。

于 2012-03-13T16:51:15.580 に答える