2016-11-22 14 views
0

いくつかのデータを2つのMYSQLテーブルに挿入しようとしています。 第2のテーブルは、第1のテーブル行Idを外部キーとして格納する。 私はこのコードをうまく動作しますが、それは遅いです。それをより速くする最善の方法は何ですか?複数のMYSQLテーブルへの挿入方法C#高速?

string ConnectionString = "server=localhost; password = 1234; database = DB ; user = Jack"; 
     MySqlConnection mConnection = new MySqlConnection(ConnectionString); 
     mConnection.Open(); 
     int index = 1; 


     for (int i = 0; i < 100000; i++) 
     { 

      string insertPerson = "INSERT INTO myentities(Name) VALUES (@first_name);" 
        + "INSERT INTO secondtable(Id, Name,myentities) VALUES (@ID, @city, LAST_INSERT_ID());"; 
      MySqlCommand command = new MySqlCommand(insertPerson, mConnection); 
      command.Parameters.AddWithValue("@first_name", "Jack"); 
      command.Parameters.AddWithValue("@ID", i+1); 

      command.Parameters.AddWithValue("@city", "Frank"); 

      command.ExecuteNonQuery(); 
      command.Parameters.Clear(); 
     } 

私はStackOverflowの質問のいずれかに次のコードを発見したが、それだけではなく、外部キーを介して接続されている複数のテーブルに単一のテーブルにデータを挿入しました。 このコードはかなり高速ですが、私はそれを複数のテーブルでどのように動作させることができるのかよくわかりませんでした。

public static void BulkToMySQL() 
{ 
    string ConnectionString = "server=192.168.1xxx"; 
    StringBuilder sCommand = new StringBuilder("INSERT INTO User (FirstName, LastName) VALUES ");   
    using (MySqlConnection mConnection = new MySqlConnection(ConnectionString)) 
    { 
     List<string> Rows = new List<string>(); 
     for (int i = 0; i < 100000; i++) 
     { 
      Rows.Add(string.Format("('{0}','{1}')", MySqlHelper.EscapeString("test"), MySqlHelper.EscapeString("test"))); 
     } 
     sCommand.Append(string.Join(",", Rows)); 
     sCommand.Append(";"); 
     mConnection.Open(); 
     using (MySqlCommand myCmd = new MySqlCommand(sCommand.ToString(), mConnection)) 
     { 
      myCmd.CommandType = CommandType.Text; 
      myCmd.ExecuteNonQuery(); 
     } 
    } 
} 
+0

あなたが見つけたコードも痛いほど安全ではありません。それは事実上ハッキングされることを懇願しています。それを使用しないでください。 –

答えて

1

可能な限り速い方法は、.NET MySQLコネクタ経由でループ内でmysqlを呼び出さないという戦略を策定することです。特にi = 0〜99999の場合。 LOAD DATA INFILEと輸入をdbにCSVスルー:直接dbテーブルの操作やケースB:あなたはこれを達成するための方法は、スルーCASE Aのいずれかです。 CASE Bでは

ステージング表またはテーブルにそのデータを持参することが多いが賢明です。特定の状況に応じて、データ準備のためのチェックを行うことができます。つまり、スクラブする必要のある外部データを取得している可能性があります(ETL)。その他のメリットとしては、消費に適していない本物のテーブルに不当なデータをコミットしないことです。だから、中止オプションがあなたに公開されています。

今すぐパフォーマンス逸話に。 2016年後半のMySQLと.NET Connectorバージョン6.9.9.0では、このルートを使用することで最大40倍のパフォーマンス向上を達成できます。 INSERTクエリを呼び出さないと不自然に思えるかもしれませんが、私はループしていません。確かに、小さなループでは、バルクでのデータ取り込みではありません。 500行もありません。いくつかのルーチンを再作成すると、顕著なUXの改善が見られます。

これは真に外部から来たデータのためのものです。 ケースA:上記のデータベースに既にある通常のデータは適用されません。そのような状況では、サーバー側でできるだけデータをマッサージするようにSQLを作成するように努めます(100%読んでください)。そのため、データをクライアントに戻すことなく、クライアント側でConnectorルーピングコールを使用してサーバーに戻す必要がありません。これはストアドプロシージャを必ずしも必要とせず、まったく必要としません。クライアント転送に向かわずにデータを操作し、バックアップしたクライアント側の呼び出しは、あなたが撮影したものです。

0

あなたは10万回が繰り返されない何もするので、ループの外に不要な動作を移動することによって、いくつかの改善を得ることができます:

string insertPerson = 
    "INSERT INTO myentities(Name) VALUES (@first_name);" 
    + "INSERT INTO secondtable(Id, Name,myentities) VALUES (@ID, @city, LAST_INSERT_ID());"; 
string ConnectionString = "server=localhost; password = 1234; database = DB ; user = Jack"; 

using (var Connection = new MySqlConnection(ConnectionString)) 
using (var command = new MySqlCommand(insertPerson, mConnection)) 
{ 
    //guessing at column types and lengths here 
    command.Parameters.Add("@first_name", MySqlDbType.VarChar, 50).Value = "Jack"; 
    var id = command.Parameters.Add("@ID", MySqlDbType.Int32); 
    command.Parameters.Add("@city", MySqlDbType.VarChar, 50).Value = "Frank"; 


    mConnection.Open(); 
    for (int i = 1; i <= 100000; i++) 
    { 
     id.Value = i; 
     command.ExecuteNonQuery(); 
    } 
} 

をしかしほとんどは、あなたがこのシナリオを避けるにしてみてください。代わりに、数値テーブルを使用して両方のテーブルの結果を事前に投影するようなやり方をします。ロックを設定するための外部キー制約付きのsome things you can doがあります(部分的に挿入されたレコードを挿入または読み込もうとすると悪いキーを避けるためにテーブル全体をロックする必要があります)、トランザクションログ(各レコードではなく、変更)と外部キーの強制(挿入を処理している間は無効にすることができます)。

関連する問題