【问题标题】:MySql Insert Ignore performanceMySql 插入忽略性能
【发布时间】:2013-08-02 02:31:45
【问题描述】:

我必须在 MySql 表中插入 90Mb 的数据,并且我正在使用 INSERT IGNORE 命令来避免重复键的异常。性能是每秒 8 条记录,但似乎很慢。我可以快点吗?

附言因为我从 sql 紧凑型数据库中读取数据,所以我正在为每条记录插入记录

using (SqlCeConnection sqlConnection = new SqlCeConnection(connectionstrCe))
            {
                sqlConnection.Open();
                SqlCeCommand cmdCe = sqlConnection.CreateCommand();
                {
                    {

                        mySQLConnection.Open();

                        foreach (KeyValuePair<string, List<string>> t in tablesCeNames) //reading the tables property from the dictionary - column names and datatypes
                        {

                            string tableData = t.Key; 
                            List<string> columnData = t.Value;
//get the values from the table I want to transfer the data
                                cmdText = "SELECT * FROM " + tableData;
//compose the mysql command
                                cmdCe.CommandText = cmdText;

                                SqlCeDataReader dataReader = cmdCe.ExecuteReader(); //read
//InsertTable is a method that get the datareader and convert all the data from this table in a list array with the values to insert
                                inputValues = InsertTables(dataReader);


                                MySql.Data.MySqlClient.MySqlTransaction transakcija;
                                transakcija = mySQLConnection.BeginTransaction();

                                worker.ReportProgress(4, inputValues.Count);

                                foreach (string val in inputValues)//foreach row of values of the data table
                                {
                                    cmdSqlText = "INSERT IGNORE INTO " + tableData + "("; //compose the command for sql

                                    foreach (string cName in columnData)  //forach column in a table
                                    {
                                        string[] data = cName.Split(' ');
                                        if (!data[0].ToString().Equals("Id"))
                                        {
                                            cmdSqlText += data[0].ToString() + ","; //write the column names of the values that will be inserted  
                                        }
                                    }
                                    cmdSqlText = cmdSqlText.TrimEnd(',');
                                    cmdSqlText += ") VALUES (";
//val contains the values of this current record that i want to insert
                                    cmdSqlText += val;  //final command with insert ignore and the values of one record
                                    if (!val.Equals(""))
                                    {
                                        try
                                        {
                                            new MySql.Data.MySqlClient.MySqlCommand(cmdSqlText, mySQLConnection, transakcija).ExecuteNonQuery(); //execute insert on sql database
                                            WriteToTxt("uspješno upisano u mysql" + t.Key);
                                        }
                                        catch (MySql.Data.MySqlClient.MySqlException sqlEx)
                                        {
                                        }
                                    }
                                }

                                if (TablicaSveOK)
                                {
                                    transakcija.Commit();

                                }
                                else
                                {
                                    transakcija.Rollback();
                                }
                            }
                        }

                        if (mySQLConnection.State != System.Data.ConnectionState.Closed)
                        {
                            mySQLConnection.Close();
                        }
                    }

【问题讨论】:

  • 一种方法是在你的循环中构建一个字符串构建器并在外部进行插入......这将减少每条记录访问数据库的热量
  • @Sam 你的意思是每次插入一组记录?
  • 可能你的代码可能被 otpmized 了很多,但没有看到它.....
  • 是的,它可以节省您每次点击 db 并进行批量插入
  • 进一步说明@Sam 的观点,我经常这样做。可能最简单的方法是敲一个类来做插入。实例化该类的一个实例。对于每条记录,您将行传递给对象,它决定是否有足够的行来添加。如果不是,它将该行添加到等待行的存储中,如果有足够的行,它会立即对所有这些行执行 INSERT IGNORE,然后清除等待行的存储。处理完所有行后,您将销毁对象,并在类的 destruct 方法中进行最终插入。

标签: c# mysql sql-server-ce


【解决方案1】:

从 Sql 获取数据到文件并使用 LOAD DATA 怎么样?

http://dev.mysql.com/doc/refman/5.0/es/load-data.html

【讨论】:

    【解决方案2】:

    而不是发送多个调用,您可以发送一个调用来插入所有记录。像这样插入

    insert into your table(col1, col2)
    SELECT 'Name1', 'Location1' 
    UNION ALL
    SELECT 'Name2', 'Location2'
    UNION ALL
    SELECT 'Name3', 'Location3'
    

    其中一部分可能是您的代码是瓶颈而不是插入语句。所以我建议你先检查问题出在哪里,然后再寻找解决方案。

    【讨论】:

      【解决方案3】:

      最新的 MySql.Connector 有一个名为 MySqlBulkLoader 的类,可用于以更面向 NET 的方式调用 MySql 的 LOAD DATA 语法。该类需要一个逗号分隔值文件来加载,而且速度非常快。

      因此,您的工作是读取数据表中的所有 Sql Compact 记录,然后使用流写入器或专门的 CSV 写入器将所有内容写入文件中。

      然后将数据加载到 MySql 表中的代码就像这样简单

      string connStr = "server=localhost;user=root;database=........";
      using(MySqlConnection conn = new MySqlConnection(connStr))
      {
           MySqlBulkLoader bl = new MySqlBulkLoader(conn);
           bl.TableName = "yourdestinationtable";
           bl.FieldTerminator = "\t";
           bl.LineTerminator = "\n";
           bl.FileName = "path_to_your_comma_separated_value_file";
           try
           {
              conn.Open();
              int count = bl.Load();
           }
      }
      

      【讨论】:

      • 我有很多不需要插入的重复值使用这个 bulkLoader 有问题吗?
      • 您可以将所有数据插入一个单独的临时表中,然后运行一个存储过程来协调数据。所有这些都将在服务器上运行,因此不会影响加载数据所需的时间
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      • 1970-01-01
      • 2012-08-11
      • 2019-02-16
      • 1970-01-01
      • 2012-06-09
      • 2011-09-11
      相关资源
      最近更新 更多