我的问题:代码运行得很好,但速度对于它需要处理的行数来说太慢了。
我正在做什么:我启动一个 COUNT(*) 来提取总行数(昨晚约为 58000),然后使用它来创建循环来执行以下操作:从该行中提取两列数据,数据挖掘一列文本模式。
完成此操作后,我会搜索第二个表以查看该用户名是否已存在 - 如果存在,我会更新其行。如果没有,我添加一个新的。
有 44 列数据,其中一列是名称,另外 43 列存储我的数据挖掘结果的值。
在大约 8 小时内,它已经完成了刚开始时的 58000 个中的 26500 个(在同一时期,该表已增长到约 100000 个,但我并不担心这一点)。
有没有更好的方法来提高读/写速率?
我的部分代码 - 我删除了许多 int 声明和 Regex.Matches,因为它们是第一个声明和 Regex.Matches 的副本,并更改了 Match 值。
azCheck 是确定消息是否包含我们要查找的任何内容,它仍然是“0”,然后我们就不必理会代码的最后部分。
using (new MySqlConnection(ConnectiongString))
{
using (MySqlCommand cmd = new MySqlCommand("select count(*) from messages", connection))
{
using (MySqlDataReader reader = cmd.ExecuteReader())
{
StringBuilder sb = new StringBuilder();
while (reader.Read())
{
sb.Append(reader.GetInt32(0).ToString());
}
total_messages = int.Parse(sb.ToString());
}
}
}
Console.WriteLine(total_messages.ToString());
connection.Close();
for (int i = 1; i <= total_messages; i++)
{
connection.Open();
using (new MySqlConnection(ConnectiongString))
{
using (MySqlCommand cmd = new MySqlCommand("select * from messages WHERE id="+i+"", connection))
{
using (MySqlDataReader reader = cmd.ExecuteReader())
{
StringBuilder sb = new StringBuilder();
while (reader.Read())
{
username = reader["username"].ToString();
message = reader["message"].ToString();
}
}
}
}
connection.Close();
Console.Write("\r{0} ", i);
int aiCount = 0;
aiCount += Regex.Matches(message, "ai", RegexOptions.IgnoreCase).Count;
azCheck += aiCount;
//There are ~42 of the regex.matches after the first one.
MySqlCommand cmd1 = connection.CreateCommand();
connection.Open();
cmd1.CommandText = "SELECT username FROM users";
cmd1.CommandType = CommandType.Text;
cmd1.Connection = connection;
MySqlDataReader dr = cmd1.ExecuteReader();
while (dr.Read())
{
if (dr[0].ToString() == username)
{
check++;
}
}
connection.Close();
if (check == 0)
{
MySqlConnection connection2 = new MySqlConnection(ConnectiongString);
connection2.Open();
try
{
MySqlCommand cmd2 = connection2.CreateCommand();
cmd2.CommandText = "INSERT INTO users (username,aiCount) VALUES (@username,@aiCount)";
cmd2.Parameters.AddWithValue("@username", username);
cmd2.Parameters.AddWithValue("@aiCount", aiCount);
cmd2.ExecuteNonQuery();
connection2.Close();
}
catch (Exception)
{
throw;
}
} else {
int aiCount_old = 0;
if (azCheck > 0)
{
//Here we are taking the existing values from this users row,
//which we then add the new values from above and save.
MySqlConnection connection4 = new MySqlConnection(ConnectiongString);
connection4.Open();
try
{
MySqlCommand cmd2 = connection4.CreateCommand();
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = "SELECT * from users WHERE username = @username";
cmd2.Parameters.AddWithValue("@username", username);
MySqlDataReader reader = cmd2.ExecuteReader();
while (reader.Read())
{
aiCount_old = Convert.ToInt32(reader["aiCount"].ToString());
}
}
catch (Exception)
{
throw;
}
connection4.Close();
aiCount += aiCount_old;
MySqlConnection connection5 = new MySqlConnection(ConnectiongString);
connection5.Open();
try
{
MySqlCommand cmd4 = connection5.CreateCommand();
cmd4.CommandType = CommandType.Text;
cmd4.CommandText = "UPDATE users SET aiCount = @aiCount WHERE LOWER(LTRIM(RTRIM(username))) = @username";
cmd4.Parameters.AddWithValue("@username", username.Trim().ToLower());
cmd4.Parameters.AddWithValue("@aiCount", aiCount.ToString());
cmd4.ExecuteNonQuery();
Console.WriteLine("User updated.");
}
catch (Exception ex)
{
throw;
}
connection5.Close();
最佳答案
您有几个效率低下的地方,我可以立即发现。
您不断地打开和关闭连接字符串。这可能是你最大的瓶颈。打开连接一次,然后在完成所有处理后关闭连接一次,您可能会看到性能的大幅提升。
您还可以使用不同的连接对象,这将减少打开和关闭连接的需要。
您似乎还对连接对象上“using”的使用存在误解。我看到 using (new MySqlConnection(ConnectiongString))
,但是该代码完全无用,因为它除了初始化连接对象之外不执行任何操作,该对象会立即丢失,因为它没有分配给对象.
由于您按顺序处理所有内容,因此在每种情况下都使用 connection
作为连接对象,仅在处理开始时打开它,并在处理完成时关闭它,然后执行 Dispose 方法(using
语句的要点)。
仅此更改就可以将处理时间减少一个数量级。
注意:如果您需要在数据读取器打开时进行更新或其他查询,则需要为数据读取器建立单独的连接。
关于C# - SQL - 读取数据库中的每一行,对行进行数据挖掘,然后将结果保存在另一个数据库中 - 如何提高速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32253557/