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

.Net C# Connector/Net Parameters very slow

我正在使用 .net MYSQL 连接器:https://dev.mysql.com/downloads/file.php?id=455843 在 C# 中建立 mysql 连接。我已经在本地主机 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 分析器。它告诉我他总共提出了 4 个请求 => 它与数据库无关。

一旦我将 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 刷新集合。谢谢。

解决方案是这样的

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();
    }

如评论中所述。

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

要解决此问题,您需要:

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

在第一次创建命令对象时设置没有值的参数。然后,在每次迭代中设置值。如果名称和数据类型不变,实际上不需要每次都清除并重新添加参数。