2

プログラムの寿命の終わりに、6 つの異なるリストの内容全体をデータベースにアップロードするコードがあります。問題は、それらがそれぞれ約 14,000 のアイテムを含む並列リストであり、個別のアイテムごとに挿入クエリを実行する必要があることです。これには時間がかかります。これを行うより速い方法はありますか? 関連するコードのサンプルを次に示します。

    public void uploadContent()
    {
        var cs = Properties.Settings.Default.Database;
        SqlConnection dataConnection = new SqlConnection(cs);
        dataConnection.Open();

        for (int i = 0; i < urlList.Count; i++)
        {
            SqlCommand dataCommand = new SqlCommand(Properties.Settings.Default.CommandString, dataConnection);
            try
            {
                dataCommand.Parameters.AddWithValue("@user", userList[i]);
                dataCommand.Parameters.AddWithValue("@computer", computerList[i]);
                dataCommand.Parameters.AddWithValue("@date", timestampList[i]);
                dataCommand.Parameters.AddWithValue("@itemName", domainList[i]);
                dataCommand.Parameters.AddWithValue("@itemDetails", urlList[i]);
                dataCommand.Parameters.AddWithValue("@timesUsed", hitsList[i]);

                dataCommand.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                using (StreamWriter sw = File.AppendText("errorLog.log"))
                {
                    sw.WriteLine(e);
                }
            }

        }
        dataConnection.Close();
    }

コードが構成ファイルから取得するコマンド文字列は次のとおりです。

コマンド文字列:

INSERT dbo.InternetUsage VALUES (@user, @computer, @date, @itemName, @itemDetails, @timesUsed)
4

4 に答える 4

2
  1. コマンドとパラメーターの作成を for の外部で行う (int i = 0; i < urlList.Count; i++)
  2. また、トランザクション内に挿入を作成します
  3. 可能であれば、ストアド プロシージャを作成し、パラメーターを DataTable として渡します。
于 2012-10-23T13:25:43.250 に答える
2

@aleryaの回答で述べたように、次のことを行うと役立ちます(ここに説明を追加)

1) コマンドとパラメータの作成を for ループの外側にする 毎回同じコマンドを使用しているため、毎回コマンドを作成し直すのは意味がありません。新しいオブジェクトを作成する (時間がかかる) ことに加えて、いくつかのこと (テーブルが存在するなど) のために作成されるたびにコマンドを検証する必要があります。これにより、多くのオーバーヘッドが発生します。

2) 挿入をトランザクション内に 置く デフォルトでは、トランザクション内にないコマンドはそれ自体のトランザクションと見なされるため、すべての挿入をトランザクション内に置くと速度が上がります。したがって、何かを挿入するたびに、データベース サーバーは、挿入されたものが実際に保存されていることを確認する必要があります (通常は、ディスクの速度によって制限されるハード ディスク上)。ただし、複数の INSERT が 1 つのトランザクション内にある場合、チェックは 1 回だけ実行する必要があります。

既に示したコードに基づいたこのアプローチの欠点は、1 つの不適切な INSERT が束を台無しにすることです。これが許容されるかどうかは、特定の要件によって異なります。

余談 ですが、もう 1 つすべきことは、IDisposable インターフェイスを適切に使用することです (ただし、これは短期的には高速化されません)。これは、すべての IDisposable オブジェクト (SqlConnection、SqlCommand) で .Dispose() を呼び出すか、理想的にはそれらを using() ブロックでラップすることを意味します。

using( SqlConnection dataConnection = new SqlConnection(cs) 
{
    //Code goes here
}

これにより、ループが大きくなりすぎるとすぐに問題になる、これらのスポットからのメモリ リークを防ぐことができます。

于 2012-10-23T13:41:41.570 に答える
1

データベースに INSERT コマンドを 1 つずつ送信すると、データベース サーバーへのラウンド トリップが発生するため、プロセス全体が実際に遅くなります。パフォーマンスが心配な場合は、一括挿入戦略の使用を検討する必要があります。あなたは出来る:

  1. BULK INSERT が理解できる形式で、すべての情報を含むフラット ファイルを生成します。
  2. BULK INSERT コマンドを使用して、そのファイルをデータベースにインポートします ( http://msdn.microsoft.com/en-us/library/ms188365(v=sql.90).aspx )。

Ps。SQL というと、MS SQL Server を使用していると思います。

于 2012-10-23T13:39:02.337 に答える
-1

別のスレッドから uploadContent()メソッドを実行してみませんか。
これにより、クエリの実行にかかる時間を気にする必要がなくなります。

于 2012-10-23T13:31:22.720 に答える