【问题标题】:List <system.Datarow> vs List <EntityClass>, which would be faster? [closed]List <system.Datarow> vs List <EntityClass>,哪个更快? [关闭]
【发布时间】:2020-10-08 16:47:57
【问题描述】:

我正在从数据库中加载大约 400 万条记录并一次处理一行。为此,我正在遍历数据集的每个数据行,这会导致效率问题。

我怎样才能加快速度?我尝试使用 Parallel.Foreach 循环。但是,由于我正在处理不是线程安全的数据行,因此在我写入数据行的位置周围实施锁定块会降低效率。逻辑大约有 3k 行长。所以每一行都运行了 3k 行。

有什么方法可以提高效率吗?我正在考虑使用 DataRows 列表而不是使用 DataRows 本身。如果我做出这样的改变,我是否能够使用 Parallel.Foreach 循环并期待更高的效率?

或者我应该为报告创建一个实体类并创建该实体类的列表?哪个会更快? System.DataRow 列表还是实体类列表?

我明白这是一个设计问题,但我对此无能为力。我会很感激任何帮助。谢谢。

【问题讨论】:

    标签: c# winforms datatable dataset datarow


    【解决方案1】:

    我建议使用datareader 一次处理一行,而不是将 400 万行加载到数据表中。这应该会大大加快加载过程。

    为了加快处理速度,您可以在 C# 3000 行代码中编写一个异步方法,为每一行调用它。使用 Task.WhenAll 并行运行它们。你可以向上System.Net.ServicePointManager.DefaultConnectionLimit 最大化并行度。

    这是它的样子

    public async Task LoadData(SqlConnection connection)
        {
            using (connection)
            {
                SqlCommand command = new SqlCommand(
                  "SELECT colOne, colTwo, colThree FROM SqlTable;",
                  connection);
                connection.Open();
    
                SqlDataReader reader = command.ExecuteReader();
                var tasks = new List<Task>();
    
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        tasks.Add(ProcessData(reader.GetInt32(0), reader.GetInt32(1), reader.GetInt32(2)));
                    }
    
                    await Task.WhenAll(tasks);
                }
                else
                {
                    Console.WriteLine("No rows found.");
                }
                reader.Close();
            }
        }
    
        public async Task ProcessData(int one, int two, int three)
        { 
            // lots of processing
    
            // open a new connection to database to update row and close it.
        }
    

    希望对您有所帮助。

    【讨论】:

    • 感谢您的回复。数据阅读器不是只读的只进游标吗?我还需要将一些数据写入数据集中。例如:假设我的数据表有 3 列,基于 3 列值的组合,我需要在数据表中创建一个新列并为该列分配一个值。 (读写)另外,我认为与数据库建立开放连接比方说 40 分钟并不是一个好习惯,因为 DataReader 需要开放连接(当前运行时)
    • 我错过了关于回信的部分。您是将新列保存回数据库还是仅在 UI 中使用?
    • 报告是从 3 个独立的模块调用的。在两个模块中,我们将其显示在 UI 中,但在第三个模块中,我们将其写回数据库。
    【解决方案2】:

    DataTables“对于多线程读取操作是安全的。您必须同步任何写入操作。”

    https://docs.microsoft.com/en-us/dotnet/api/system.data.datatable?view=netcore-3.1

    但如果您可以避免将 4M 行加载到 DataTable 中,那就更好了。如果您可以得到按数据库排序的结果,那么您可以在最初加载数据时高效地进行分组。

    【讨论】:

    • 嗨,大卫。除了将数据加载到数据表中之外,我还需要在数据表中创建一个新列,并根据数据表中存在的值(从数据库加载)为其分配一个值。我不太明白你在最后一行的意思,你能详细说明一下吗?
    • 定义数据表或类不是为了查询的结果,而是为了报表的需要。然后在从源中读取结果时,使用 DataReader 对结果进行流式传输、分组和计算。
    猜你喜欢
    • 2022-11-20
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-23
    • 2011-03-13
    • 2020-02-12
    相关资源
    最近更新 更多