.Net C#Connector / Net参数非常慢

时间:2015-07-01 09:57:56

标签: c# .net mysql-connector

我正在使用.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();
    }

1 个答案:

答案 0 :(得分:1)

如评论中所述。

命令对象正在循环中重用 - 每行一个输入语句。在每次迭代中,您为16个参数中的每个参数调用command.Parameters.AddWithValue。这意味着您的参数集合每行增加16个。

要解决此问题,您需要:

在添加它们的foreach循环之前清除参数

首次创建命令对象时,设置不带值的参数。然后,在每次迭代时设置值。如果名称和数据类型未更改,您实际上不需要每次都清除并重新添加参数。