如何在 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 表的最佳方法