【发布时间】:2016-09-24 08:24:03
【问题描述】:
我需要每分钟向本地数据库插入 388 个数据。 起初,当表为空时,我只需要 5 秒即可插入数据库。
但是当表变大时,当行数达到 1,026,558 时,程序效率会减慢到一分钟以上。
并且CPU的使用率是100%。这很不寻常。
这是我的代码:
public static void dataToDB(String[] routeIDArray,String[] levelArray,String[] valueArray,String[] travelTimeArray, int amountOfData)
{
MySqlConnection con = new MySqlConnection(connStr);
MySqlCommand cmd = null;
MySqlDataReader rdr = null;
String sqlCmd, updateSqlCmd = "UPDATE `datetimetable` SET ";
for(int counter = 0; counter < amountOfData; counter++)
{
sqlCmd = "ALTER TABLE `datetimetable` ADD COLUMN IF NOT EXISTS `" + routeIDArray[counter] + "` INT NULL;"
+ "INSERT INTO `roadvalue`.`data` (`level`,`value`,`traveltime`) VALUES ("
+ levelArray[counter] + ","
+ valueArray[counter] + ","
+ travelTimeArray[counter] + ");"
+ "SELECT LAST_INSERT_ID() FROM `data`;";
cmd = new MySqlCommand(sqlCmd, con);
con.Open();
rdr = cmd.ExecuteReader();
rdr.Read();
updateSqlCmd += "`" + routeIDArray[counter] + "` = " + rdr[0] + ",";
rdr.Close();
}
updateSqlCmd = updateSqlCmd.TrimEnd(',');
updateSqlCmd += " WHERE EXISTS (SELECT * WHERE dateTime = '" + dateTime.ToString("yyyy-MM-dd HH:mm:00") + "');";
cmd = new MySqlCommand(updateSqlCmd, con);//update data key to datetimetable
cmd.ExecuteNonQuery();
Console.WriteLine("Done.");
con.Close();
}
public static void checkDateTimeExisted()
{
MySqlConnection con = new MySqlConnection(connStr);
MySqlCommand cmd;
String sqlCmd;
sqlCmd = "INSERT INTO `datetimetable` (`dateTime`) SELECT * FROM (SELECT '" + dateTime.ToString("yyyy-MM-dd HH:mm:00")
+ "') AS tmp WHERE NOT EXISTS(SELECT `dateTime` FROM `datetimetable` WHERE `dateTime` = '" + dateTime.ToString("yyyy-MM-dd HH:mm:00") + "') LIMIT 1; ";
con.Open();
cmd = new MySqlCommand(sqlCmd, con);
cmd.ExecuteNonQuery();
con.Close();
}
Mysql Engine 是 InooDB,表“data”有一个 Auto_Increment 主键,表“datetimetable”有一个 Auto_Increment 主键和一个不重复的 datetime 作为索引。
我做错了什么?
【问题讨论】:
-
routeIDArray[counter]有多少个不同的值?尤其是对于大表,更改它们是一个巨大的、巨大的、巨大的性能杀手——你应该尝试一种不同的方式来实现你想要实现的任何目标 -
我使用Thread运行dataToDB(),每50个数据运行一个线程。
-
所以我理解正确,不是让您的代码线程安全,而是按需为每个线程创建一个新列?您可以尝试在一个线程中运行所有插入,没有额外的列,使用准备好的语句和事务内部。应该会给您带来巨大的性能提升。哦:打开/关闭你的数据库连接一次。这也是一个巨大的杀手。
-
我的第一个想法是一次性插入所有数据(
insert into roadvalue.data(...) values (a,b,c),(a,b,d),(...)),然后更新你的datetimetable(你甚至不需要准备它,数据是在roadvalue.data中,加入它。作为一般规则:您不想为新的 routeid 添加列。您想更改数据模型以在行中使用它们。 -
我删除了alter命令,但是效果还是很慢。