我正在使用.net MYSQL连接器:https://dev.mysql.com/downloads/file.php?id=455843在C#中建立一个mysql连接。我在我的localhost Windows上安装了MariaDB 10.0。数据库引擎是MyISAM。
问题:
我必须从现有的csv文件中进行大约500k的插入。为了使源更具可读性,我使用了准备好的语句。这花了我大约38秒来处理1000行。显然这是很重要的。注意:我甚至没有尝试使用参数执行查询。
public void process(String commandText, Dictionary<string, string> param, int satz)
{
command.CommandText = commandText;
// command.Prepare();
Console.WriteLine(satz);
foreach(KeyValuePair<string, string> pair in param)
{
try {
command.Parameters.AddWithValue(pair.Key, pair.Value);
} catch (MySqlException ex)
{
/* some stuff */
}
}
// command.ExecuteNonQuery();
}
因为我不知道究竟是什么AddWithValue我检查了一个sql profiler。它告诉我他总共提出了4个请求=&gt;它不是数据库相关的。
一旦我将commandText更改为不带参数的直接INSERT语句,该函数花了我大约0.8秒。
public void process(String commandText, Dictionary<string, string> param, int satz)
{
command.CommandText = commandText;
// command.Prepare();
Console.WriteLine(satz);
foreach(KeyValuePair<string, string> pair in param)
{
try {
//command.Parameters.AddWithValue(pair.Key, pair.Value);
//command.Parameters[pair.Key].DbType = System.Data.DbType.AnsiString;
} catch (MySqlException ex)
{
/*if (ex.ErrorCode == -2147467259)
continue;
else
throw ex;*/
}
}
command.ExecuteNonQuery();
}
这是生成的SQL查询
public void process210(String[] attributes)
{
if (++line210 > 1000) return;
Console.Write(line210+" : ");
// String commandText = "INSERT INTO Programm (Serien_Nr, Prog_Schluessel, Prog_Name, Preisfeld, Front_Tiefe, Preisgruppe, Preisfeld_Block, Lieferbar_ab, Lieferbar_bis, Frontauspraegungs_ID, Frontgruppe, Var_Familien_Nr, Varianten_Art_Front, Var_Schluessel_Front, Mindest_Lieferzeit, Hersteller_ID) values (@Serien_Nr, @Prog_Schluessel, @Prog_Name, @Preisfeld, @Front_Tiefe, @Preisgruppe, @Preisfeld_Block, @Lieferbar_ab, @Lieferbar_bis, @Frontauspraegungs_ID, @Frontgruppe, @Var_Familien_Nr, @Varianten_Art_Front, @Var_Schluessel_Front, @Mindest_Lieferzeit, @Hersteller_ID) ;";
String programm_Serien_Nr = attributes[1].Replace("\"", "").Replace(";", "");
String programm_Prog_Schluessel = attributes[2].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Prog_Name = attributes[3].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Preisfeld = attributes[4].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Front_Tiefe = attributes[5].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Preisgruppe = attributes[6].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Preisfeld_Block = attributes[7].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Lieferbar_Ab = attributes[8].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Lieferbar_Bis = attributes[9].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Frontauspraegungs_ID = attributes[10].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Frontgruppe = attributes[11].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Var_Familien_Nr = attributes[12].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Varianten_Art_Front = attributes[13].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Var_Schluessel_Front = attributes[14].Replace("\\", "").Replace("\"", "").Replace(";", "");
String programm_Mindest_Lieferzeit = attributes[15].Replace(";", "").Replace("\\", "").Replace("\"", "");
String commandText = "INSERT INTO Programm (Serien_Nr, Prog_Schluessel, Prog_Name, Preisfeld, Front_Tiefe, Preisgruppe, Preisfeld_Block, Lieferbar_ab, Lieferbar_bis, Frontauspraegungs_ID, Frontgruppe, Var_Familien_Nr, Varianten_Art_Front, Var_Schluessel_Front, Mindest_Lieferzeit, Hersteller_ID) values (\""+ programm_Serien_Nr + "\", \"" + programm_Prog_Schluessel + "\", \"" + programm_Prog_Name + "\", \"" + programm_Preisfeld + "\", \"" + programm_Front_Tiefe + "\", \"" + programm_Preisgruppe + "\", \"" + programm_Preisfeld_Block + "\", \"" + programm_Lieferbar_Ab + "\", \"" + programm_Lieferbar_Bis + "\", \"" + programm_Frontauspraegungs_ID + "\", \"" + programm_Frontgruppe + "\", \"" + programm_Var_Familien_Nr + "\", \"" + programm_Varianten_Art_Front + "\", \"" + programm_Var_Schluessel_Front + "\", \"" + programm_Mindest_Lieferzeit + "\", \"" + hersteller_id + "\") ;";
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("@Serien_Nr", attributes[1]);
dictionary.Add("@Prog_Schluessel", attributes[2]);
dictionary.Add("@Prog_Name", attributes[3]);
dictionary.Add("@Preisfeld", attributes[4]);
dictionary.Add("@Front_Tiefe", attributes[5]);
dictionary.Add("@Preisgruppe", attributes[6]);
dictionary.Add("@Preisfeld_Block", attributes[7]);
dictionary.Add("@Lieferbar_ab", attributes[8]);
dictionary.Add("@Lieferbar_bis", attributes[9]);
dictionary.Add("@Frontauspraegungs_ID", attributes[10]);
dictionary.Add("@Frontgruppe", attributes[11]);
dictionary.Add("@Var_Familien_Nr", attributes[12]);
dictionary.Add("@Varianten_Art_Front", attributes[13]);
dictionary.Add("@Var_Schluessel_Front", attributes[14]);
dictionary.Add("@Mindest_Lieferzeit", attributes[15]);
dictionary.Add("@Hersteller_ID", hersteller_id);
process(commandText, dictionary, 210);
}
任何想法为什么它如此可怕缓慢?我很想使用预处理语句,因为它大大提高了代码的可读性。
修改
就像Andy Nichols说我忘了在执行后从MysqlCommand刷新Collection。谢谢。
解决方案就像这样
public static void process(String commandText, Dictionary<string, string> param, int satz)
{
command = new MySqlCommand();
command.Connection = con;
command.CommandText = commandText;
command.Prepare();
foreach (KeyValuePair<string, string> pair in param)
{
try {
command.Parameters.AddWithValue(pair.Key, pair.Value);
} catch (MySqlException ex)
{
/* stuff */
}
}
command.ExecuteNonQuery();
}
答案 0 :(得分:1)
如评论中所述。
命令对象正在循环中重用 - 每行一个输入语句。在每次迭代中,您为16个参数中的每个参数调用command.Parameters.AddWithValue
。这意味着您的参数集合每行增加16个。
要解决此问题,您需要:
在添加它们的foreach循环之前清除参数
或
首次创建命令对象时,设置不带值的参数。然后,在每次迭代时设置值。如果名称和数据类型未更改,您实际上不需要每次都清除并重新添加参数。