向 Mysql 插入数据越来越慢
Insert data to Mysql getting slower and slower
我需要每分钟插入 388 个数据到本地数据库。
起初当 table 为空时,我只需要 5 秒即可插入到数据库。
但是当table变大时,当行数达到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引擎是InooDB,table"data"有一个Auto_Increment主键,table"datetimetable"有一个Auto_Increment 主键和一个不重复的日期时间作为索引。
我做错了什么?
我找到了答案,命令 "SELECT LAST_INSERT_ID() FROM data
;" 应该添加 LIMIT 1 否则它会得到所有的 ID 杀死性能。
不要在循环中使用 ALTER TABLE
-- 提前计划并在开始前提供所有列。
不要在一个字符串中使用多个语句。这具有安全隐患等。
当(我认为)一个简单的 WHERE
可行时,请不要使用 WHERE EXISTS...
。
如果有UNIQUE(datetime)
,那么最后的INSERT
可以简单的
INSERT IGNORE INTO datetimetable
(datetime)
VALUE
('...');
除非您需要 LAST_INSERT_ID()
,否则执行批量插入。 LIMIT 1
应该没有必要。
不要'Normalize'日期时间值;它只会减慢速度。只需将日期时间原封不动地放在主 table.
中
我需要每分钟插入 388 个数据到本地数据库。 起初当 table 为空时,我只需要 5 秒即可插入到数据库。
但是当table变大时,当行数达到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引擎是InooDB,table"data"有一个Auto_Increment主键,table"datetimetable"有一个Auto_Increment 主键和一个不重复的日期时间作为索引。
我做错了什么?
我找到了答案,命令 "SELECT LAST_INSERT_ID() FROM data
;" 应该添加 LIMIT 1 否则它会得到所有的 ID 杀死性能。
不要在循环中使用 ALTER TABLE
-- 提前计划并在开始前提供所有列。
不要在一个字符串中使用多个语句。这具有安全隐患等。
当(我认为)一个简单的 WHERE
可行时,请不要使用 WHERE EXISTS...
。
如果有UNIQUE(datetime)
,那么最后的INSERT
可以简单的
INSERT IGNORE INTO datetimetable
(datetime)
VALUE
('...');
除非您需要 LAST_INSERT_ID()
,否则执行批量插入。 LIMIT 1
应该没有必要。
不要'Normalize'日期时间值;它只会减慢速度。只需将日期时间原封不动地放在主 table.
中