如何使用 MySQL 查询在 C# 中处理大量数据?
How to handle a large data amount in C#with MySQL query?
我在 MySQL 中有大量数据,恰好 10180 行,并且它每天都在不断更新,另外还有 200-300 行。在我的 C# 应用程序中,我有一个后台工作程序,它获取数据并加载到数据表中,然后该数据表加载到显示数据的 ListView 中。
问题是这花费了大约 1 分钟,这在生产中太长了 long.I 想要修复它并优化代码。
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();} }
如果我不得不猜测是导致问题的列表视图超过数据大小。
我在一个有 50284 行的数据库上做了一个小测试。当我使用 listview 时,它花了很长时间才显示出来,我的笔记本电脑风扇开始全速运转,尽管遍历数据只花了 876 毫秒。我将测试表单切换为基本列表框,在构造函数中加载数据后仅需几秒钟即可显示。
我使用 EFCore 处理数据 connection/handling,但我认为这不会导致原始查询的性能发生巨大变化。
数据(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 核心组件,但它所做的只是包装数据库模型。我追踪了它,它只是从 db.table 发出了一个 select 废话,和你一样。它只是以 class 格式保存数据,因此您可以像普通代码一样对其进行迭代和交互。
我目前处于 Entity Framework 模式并且拥有该测试所需的所有模型代码,否则我会完成基本的 SQL 连接。查看器是这个问题的问题而不是数据大小。
一些建议
对数据行使用整数索引。整数索引可以是 3-4x faster。在您的循环中,您每行查找列索引 10 次。在循环外查找列位置一次,然后在循环内使用整数索引。
int intDateCol = dt.Columns.IndexOf("Date");
...
SubItems.Add(行[intDateCol]);
在清除项目和添加项目之前使用 ListView.BeginUpdate(),然后在完成后调用 ListView.EndUpdate()。
如果您仍然遇到性能问题,请尝试在 virtual mode 中使用 ListView。
深入了解 ListView 性能调整 here
我在 MySQL 中有大量数据,恰好 10180 行,并且它每天都在不断更新,另外还有 200-300 行。在我的 C# 应用程序中,我有一个后台工作程序,它获取数据并加载到数据表中,然后该数据表加载到显示数据的 ListView 中。
问题是这花费了大约 1 分钟,这在生产中太长了 long.I 想要修复它并优化代码。
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();} }
如果我不得不猜测是导致问题的列表视图超过数据大小。
我在一个有 50284 行的数据库上做了一个小测试。当我使用 listview 时,它花了很长时间才显示出来,我的笔记本电脑风扇开始全速运转,尽管遍历数据只花了 876 毫秒。我将测试表单切换为基本列表框,在构造函数中加载数据后仅需几秒钟即可显示。
我使用 EFCore 处理数据 connection/handling,但我认为这不会导致原始查询的性能发生巨大变化。
数据(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 核心组件,但它所做的只是包装数据库模型。我追踪了它,它只是从 db.table 发出了一个 select 废话,和你一样。它只是以 class 格式保存数据,因此您可以像普通代码一样对其进行迭代和交互。
我目前处于 Entity Framework 模式并且拥有该测试所需的所有模型代码,否则我会完成基本的 SQL 连接。查看器是这个问题的问题而不是数据大小。
一些建议
对数据行使用整数索引。整数索引可以是 3-4x faster。在您的循环中,您每行查找列索引 10 次。在循环外查找列位置一次,然后在循环内使用整数索引。
int intDateCol = dt.Columns.IndexOf("Date"); ... SubItems.Add(行[intDateCol]);
在清除项目和添加项目之前使用 ListView.BeginUpdate(),然后在完成后调用 ListView.EndUpdate()。
如果您仍然遇到性能问题,请尝试在 virtual mode 中使用 ListView。
深入了解 ListView 性能调整 here