首页 新闻 会员 周边

SqlDataAdapter.UpdateCommand更新会很慢

0
[待解决问题]

大概有10万条数据,使用SqlDataAdapter.UpdateCommand更新大概要2分钟,请教怎么解决

灬丶的主页 灬丶 | 初学一级 | 园豆:4
提问于:2023-09-08 17:13
< >
分享
所有回答(1)
0

下面是一些可能的原因和相应的优化建议:

  1. 索引:检查表上的索引是否适当。如果更新语句中的 WHERE 子句中的列没有索引,那么数据库需要扫描整个表来查找匹配的行。确保 WHERE 子句中的列有适当的索引,可以大大提高更新速度。

  2. 事务:如果更新语句在一个事务中执行,那么每次更新都会引起事务日志的写入和持久化,这会带来额外的开销。考虑将更新操作拆分为多个较小的事务,或者禁用事务(如果业务允许)。

  3. 锁定:并发访问可能导致更新语句等待其他事务的释放锁。考虑使用更细粒度的锁定策略,例如行级锁定,以减少锁冲突。

  4. 硬件和配置:检查数据库服务器的硬件配置和性能设置。确保数据库服务器具有足够的内存、磁盘空间和处理能力来处理大量的更新操作。

  5. 数据库优化:定期进行数据库优化操作,例如重新组织表、重新生成索引等。这可以帮助提高查询和更新的性能。

  6. 数据库分区:如果表的数据量非常大,可以考虑将表进行分区。分区可以将数据分散到多个物理存储位置,从而提高查询和更新的性能。

以下是多线程分页执行update的示例,我们使用 Parallel.For 方法进行并行更新操作。在每个并行任务中,我们根据页索引计算出当前页的起始行和结束行,并通过 GetPageData 方法获取当前页的数据。最后,我们使用 SqlCommand 对象执行更新操作,将数据更新到目标表中:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        string connectionString = "your_connection_string";
        string tableName = "my_table";
        int pageSize = 1000; // 每页的行数
        int pageCount = 100; // 总页数

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

           
            // 分页并行更新
            Parallel.For(0, pageCount, pageIndex =>
            {
                int startRow = pageIndex * pageSize;
                int endRow = startRow + pageSize;

                // 根据起始页码,使用分页sql获取需要更新的当页数据(主要是获取每页的主键ID)
                DataTable pageData = GetPageData(startRow, endRow);

                // 执行更新操作,每个线程更新1000条数据,并发执行
                UpdateData(connection, tableName, pageData);
            });
        }
    }


    // 获取指定页的数据
    static DataTable GetPageData(int startRow, int endRow)
    {
        DataTable pageData = ...;
        return pageData;
    }

    // 执行更新操作
    static void UpdateData(SqlConnection connection, string tableName, DataTable data)
    {
        using (SqlTransaction transaction = connection.BeginTransaction())
        {
            try
            {
                using (SqlCommand command = connection.CreateCommand())
                {
                    command.Transaction = transaction;

                    int startId = int.Parse(data.Compute("Min(id)","").ToString());
                    int endId = int.Parse(data.Compute("Max(id)","").ToString());

                    // 构建更新语句
                    command.CommandText = $"UPDATE {tableName} SET my_status = @my_status WHERE id >= @startId and id<@endId";

                    // 添加参数
                    command.Parameters.Add("@my_status", SqlDbType.Int);
                    command.Parameters.Add("@startId", SqlDbType.Int);
                    command.Parameters.Add("@endId", SqlDbType.Int);

                    // 设置参数值
                    command.Parameters["@my_status"].Value = 1; //my_status
                    command.Parameters["@startId"].Value = startId;
                    command.Parameters["@endId"].Value = endId;

                    // 执行更新操作
                    command.ExecuteNonQuery();

                }

                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                Console.WriteLine($"An error occurred: {ex.Message}");
            }
        }
    }
}
lanedm | 园豆:2381 (老鸟四级) | 2023-09-10 10:31

但是这个事务只能针对单次循序内的

支持(0) 反对(0) 灬丶 | 园豆:4 (初学一级) | 2023-09-11 08:36
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册