如何使用 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 连接。查看器是这个问题的问题而不是数据大小。

一些建议

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

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

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

  3. 如果您仍然遇到性能问题,请尝试在 virtual mode 中使用 ListView。

深入了解 ListView 性能调整 here