C# - SQL - 读取数据库中的每一行,对行进行数据挖掘,然后将结果保存在另一个数据库中 - 如何提高速度

标签 c# mysql transfer rate

我的问题:代码运行得很好,但速度对于它需要处理的行数来说太慢了。

我正在做什么:我启动一个 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/

相关文章:

c# - 打破 POCO 关系

c# - 为什么这个委托(delegate)变量为空?

php - 在服务器上安装 SSL 证书时,是否需要更改 PHP 表单提交和 MySQL 内部代码?

java - 在 Eclipse RCP 中使用拖放在 View 之间传输项目?

windows - 使用 rsync 从 Windows 传输到 Linux

c# - 如何将 sql union 转换为 linq

c# - 如何识别通用声明类型?

php - 在多个时间范围之间从mysql获取

php - A non well-formed numeric value 遇到 laravel time calculate

file - 为什么多个小文件的数据传输速度比大文件慢?