大量のデータの挿入と更新に関しては、ADO.NET は JDBC ほど優れていません。JDBC にはバッチ操作用の統合モデルがあり、非常に便利です。
PreparedStatement ps = conn.prepareStatement("arg1,args2.... の挿入または更新");
そうすればできます
for(int i=0;i<1000000000000000;i++){
ps.setXXX(realArg);
……
ps.addBatch();
if(i%500==0){ //500 個のアイテムが 1 回送信されたと仮定します
ps.executeBatch();
//パラメータバッチをクリア
}
}
ps.executeBatch();
このような操作は、非常に高いパフォーマンスをもたらすだけでなく、非常に便利です。通常、ADO.NET でこのような機能を実装するには、Addbat および CommitBat API を Command インターフェイスまたは DataAdapter インターフェイスで直接提供する必要がありますが、ADO では使用できません。 NET のただし、実装はそれほど単純ではなく、開発者は複雑な回避策を実行する必要があります。
多数の挿入操作の場合は、空の DataTable を使用して挿入する行を追加し、一定数の送信後にテーブルをクリアできます。
実装はそれほど複雑ではありません:
DateTime begin = DateTime.Now;
文字列接続文字列 = ...;
using(SqlConnection conn = new SqlConnection(connectionString))...{
conn.Open();
SqlDataAdapter sd = 新しい SqlDataAdapter();
sd.SelectCommand = new SqlCommand("CurrentTest から devid,data_time,data_value を選択", conn);
sd.InsertCommand = new SqlCommand("CurrentTest に挿入 (devid,data_time,data_value) "
+ "値(@devid,@data_time,@data_value);", conn);
sd.InsertCommand.Parameters.Add("@devid", SqlDbType.Char, 18, "devid");
sd.InsertCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.InsertCommand.Parameters.Add("@data_value", SqlDbType.Int, 8, "data_value");
sd.InsertCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;
DataSet データセット = 新しい DataSet();
sd.Fill(データセット);
ランダム r = 新しいランダム(1000);
for (int i = 0; i < 100000; i++) ...{
object[] row = ...{"DEVID"+i,DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),r.Next(1,1000) };
dataset.Tables[0].Rows.Add(行);
if (i % 300 == 0) ...{
sd.Update(dataset.Tables[0]);
データセット.テーブル[0].Clear();
}
}
sd.Update(dataset.Tables[0]);
データセット.テーブル[0].Clear();
sd.Dispose();
データセット.Dispose();
conn.Close();
}
TimeSpan ts = DateTime.Now - 開始;
MessageBox.Show("ts = " + ts.TotalMilliseconds);
このテストでは、100,000 個のデータを挿入するのに 28 秒かかりました。パフォーマンスは非常に優れています。ただし、バッチ更新や世界中の検索の例では、レコードが DataSet に入力されてから行が抽出されます。
少量のデータを使用したテストに関する限り、DataSet に 100,000 個のデータを入力しても更新するには、数百万個のデータをどのように操作する必要がありますか?つまり、これらのレコードをクエリするには、どのレコードを選択する必要があるのでしょうか?
したがって、私は引き続き空の DataTable を使用して、更新するレコードを追加します。
sd.SelectCommand = new SqlCommand("select devid,data_time,data_value from CurrentTest where 1=0", conn);
// 1=0 の条件は空のテーブルを保証します。
sd.UpdateCommand = new SqlCommand("update CurrentTest set data_time = @data_time,data_value = @data_value where devid = @devid", conn);
sd.UpdateCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.UpdateCommand.Parameters.Add("@data_value", SqlDbType.Int, 4, "data_value");
sd.UpdateCommand.Parameters.Add("@devid", SqlDbType.Char, 20, "devid");
sd.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;
for(int i=0;i<300;i++){
...................................
dataset.Tables[0].Rows.Add(行);
}
sd.Update(dataset.Tables[0]);
最初に 300 件のレコードを更新してみます。成功すると、ループ内のすべてのレコードが更新されますが、空のテーブルであるため、挿入操作には InsertCommand が必要であることが示され、この時点で RowState が追加されます。
この時点で Update がデータベースに送信されると、挿入操作が実行され、更新できなくなります。
for(int i=0;i<300;i++){
...................................
row = {初期化された値を入力};
dataset.Tables[0].Rows.Add(行);
}
データセット.AcceptChanges();
for(int i=0;i<300;i++){
...................................
データセット.テーブル[0].行[i][x] = "xxxxxxx";
...................................
}
sd.Update(dataset.Tables[0]);
まず DataTable にデータを挿入し、次に AcceptChanges() を使用して RowState を UnChanged に変更し、次にテーブル内のデータを変更して UnChanged 状態を変更します。
DataTable を現在の状態から元の状態に変更し、DataTable の行を更新すると、次のことができます。
アップデートは成功しましたが、非常に不便です。
アイデアを調整して、まずデータベースから 200 エントリ (バッチ更新のサイズ) を取得し、元の DataTable を直接取得します。
sd.SelectCommand = new SqlCommand("CurrentTest から上位 200 件の devid,data_time,data_value を選択", conn);
DataSet データセット = 新しい DataSet();
sd.Fill(データセット);
これらの 200 個のスペースを使用して、更新する他のデータを配置し、以下を確認します。
for (int i = 0; i < 100; i++)
{
dataset.Tables[0].Rows[i].BeginEdit();
dataset.Tables[0].Rows[i]["data_time"] = "2222-22-22 22:22:22";
データセット.テーブル[0].行[i]["データ値"] = 100;
dataset.Tables[0].Rows[i]["devid"] = "DEVID"+(i+10000);//DEVID10000 から DEVID10200 までレコードを更新します
dataset.Tables[0].Rows[i].EndEdit();
}
sd.Update(dataset.Tables[0]);
OK、成功しました、笑。このスペースに更新するデータを入力し続け、いっぱいになったら送信します。この方法では、100,000 個のデータを更新するのに数サイクルしかかかりません。
DateTime begin = DateTime.Now;
文字列接続文字列 = "";
using(SqlConnection conn = new SqlConnection(connectionString))...{
conn.Open();
SqlDataAdapter sd = 新しい SqlDataAdapter();
sd.SelectCommand = new SqlCommand("CurrentTest から上位 200 件の devid,data_time,data_value を選択", conn);
DataSet データセット = 新しい DataSet();
sd.Fill(データセット);
ランダム r = 新しいランダム(1000);
sd.UpdateCommand = new SqlCommand("Update CurrentTest "
+ " set data_time = @data_time,data_value = @data_value where devid = @devid", conn);
sd.UpdateCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.UpdateCommand.Parameters.Add("@data_value", SqlDbType.Int, 4, "data_value");
sd.UpdateCommand.Parameters.Add("@devid", SqlDbType.Char, 20, "devid");
sd.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;
for (int カウント = 0; カウント < 100000;)
...{
for (int i = 0; i < 200; i++,count++)
...{
dataset.Tables[0].Rows[i].BeginEdit();
dataset.Tables[0].Rows[i]["data_time"] = "2222-22-22 22:22:22";
データセット.テーブル[0].行[i]["データ値"] = 100;
dataset.Tables[0].Rows[i]["devid"] = "DEVID"+count;
dataset.Tables[0].Rows[i].EndEdit();
}
sd.Update(dataset.Tables[0]);
}
データセット.テーブル[0].Clear();
sd.Dispose();
データセットの破棄
http://www.cnblogs.com/Seabiscuit/archive/2010/05/25/1743341.html