如何在 C#with MySQL 查询中处理大量数据?

Posted

技术标签:

【中文标题】如何在 C#with MySQL 查询中处理大量数据?【英文标题】:How to handle a large data amount in C#with MySQL query? 【发布时间】:2020-09-30 06:25:01 【问题描述】:

我在 mysql 中有大量数据,正好 10180 行,并且每天都在不断更新,另外还有 200-300 行。在我的 C# 应用程序中,我有一个后台工作程序,它获取数据并加载到数据表中,然后这个数据表加载到显示数据的 ListView 中。

问题是这大约需要 1 分钟,这在生产中太长了。我想解决这个问题并优化代码。

DoWork方法里面的代码:

            try
        
            connection.Close();

            if (lvValidate.InvokeRequired)
            

                lvValidate.BeginInvoke(new MethodInvoker(delegate
                

                    lvValidate.Items.Clear();
                ));
            
            else
            
                lvValidate.Items.Clear();
            

            System.Data.DataTable dt = DataTransferDA("SELECT * FROM workhours ORDER BY ID desc");

            foreach (System.Data.DataRow row in dt.Rows)
            
                    ListViewItem tempLv = new ListViewItem(row["ID"].ToString());
                    tempLv.SubItems.Add(row["Date"].ToString());
                    tempLv.SubItems.Add(row["Name"].ToString());
                    tempLv.SubItems.Add(row["WorkCode"].ToString());
                    tempLv.SubItems.Add(row["Assembly"].ToString());
                    tempLv.SubItems.Add(row["Tech"].ToString());
                    tempLv.SubItems.Add(row["Beginning"].ToString());
                    tempLv.SubItems.Add(row["Ending"].ToString());
                    tempLv.SubItems.Add(row["Validated"].ToString());
                    tempLv.SubItems.Add(row["Validated name"].ToString());
                lvValidate.BeginInvoke(new MethodInvoker(delegate
                
                    lvValidate.Items.Add(tempLv);
                ));


            
            if (lvValidate.InvokeRequired)
            

                lvValidate.BeginInvoke(new MethodInvoker(delegate
                
                    lvValidate.TopItem = lvValidate.Items[topIndex];
                ));
            
            else
            
                lvValidate.TopItem = lvValidate.Items[topIndex];
            
            connection.Close();
        
        catch (Exception ex)  MessageBox.Show("Error happened: " + ex.Message); connection.Close(); 

【问题讨论】:

10k 对于大多数数据库来说是极少数的行(行?)。将行繁琐地添加到 ListView 的时间是浪费时间的地方。 DataBinding 和 DataGridView 需要更少的代码并且速度更快。 【参考方案1】:

一些建议

    对数据行使用整数索引。整数索引可以是3-4x faster。在您的循环中,您每行查找列索引 10 次。在循环外查找一次列位置,然后在循环内使用整数索引。

    int intDateCol = dt.Columns.IndexOf("Date"); ... SubItems.Add(row[intDateCol]);

    在清除和添加项目之前使用 ListView.BeginUpdate(),然后在完成后调用 ListView.EndUpdate()。

    如果您仍有性能问题,请尝试在virtual mode 中使用 ListView。

深入了解 ListView 性能调整here

【讨论】:

【参考方案2】:

如果我不得不猜测导致问题的列表视图超过了数据大小。

我在一个有 50284 行的数据库上做了一个小测试。当我使用列表视图时,它需要很长时间才能显示出来,并且我的笔记本电脑风扇完全倾斜,即使迭代数据只用了 876 毫秒。我将测试表单切换为基本列表框,在构造函数中加载数据后只需要几秒钟即可显示。

我使用 EFCore 进行数据连接/处理,但我认为这不会导致原始查询的性能发生巨大变化。

Data(50284) 占用了 876

            int i = 0;
            using (EFContext ctx = new EFContext())
            
                foreach(data dt in ctx.data.AsNoTracking())
                
                    i++;
                    listBox.Items.Add(dt.epc);
                
            
            watch.Stop();
            System.Diagnostics.Debug.WriteLine($"Data(i) took watch.ElapsedMilliseconds");

[编辑] EFContext 是一个 Entity Framework Core 组件,但它所做的只是包装数据库模型。我跟踪了它,它只是从 db.table 中发出了一个与您相同的 select blah。它只是将数据保存为类格式,因此您可以像普通代码一样对其进行迭代和交互。

我目前处于 Entity Framework 模式,并且拥有该测试所需的所有模型代码,否则我将完成基本的 SQL 连接。查看器是这个问题的问题而不是数据大小。

【讨论】:

嗨,我编辑了我的答案以进一步解释框架,但这绝对不是提高速度的地方,因为它只是像其他所有内容一样包装 SQL 查询。 listview vs listbox 是我看到速度提高的地方。使用 ListView 几乎破坏了我的笔记本电脑,其中列表框正常工作。 谢谢。我认为 ListView 是处理大数据模型的一个非常糟糕的主意哈哈

以上是关于如何在 C#with MySQL 查询中处理大量数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MySQL 中使用“WITH”子句?

处理具有数百万条记录更新和大量读数的 MySQL 表的最佳方法

优化返回大量记录的查询,避免数百个连接。这是一个聪明的解决方案吗?

MySQL--查询性能优化

MySQL中like查询速度慢的问题

如何做SqlServer 数据查询优化!