gpt4 book ai didi

c# - 实体模型 .net 从 MySQL 性能问题中查询 100 万条记录

转载 作者:可可西里 更新时间:2023-11-01 07:13:59 32 4
gpt4 key购买 nike

我正在使用 ADO .Net 实体模型 来查询 MySQL 数据库。我对它的实现和使用感到非常高兴。我决定看看如果我查询 100 万条记录会发生什么,并且它有严重的性能问题,但我不明白为什么。

系统挂了一段时间然后我得到了

  • 死锁异常
  • MySQL异常

我的代码如下::

      try
{
// works very fast
var data = from employees in dataContext.employee_table
.Include("employee_type")
.Include("employee_status")
orderby employees.EMPLOYEE_ID descending
select employees;

// This hangs the system and causes some deadlock exception
IList<employee_table> result = data.ToList<employee_table>();

return result;
}
catch (Exception ex)
{
throw new MyException("Error in fetching all employees", ex);
}

我的问题是为什么 ToList() 需要这么长时间?

另外,我怎样才能避免这种异常以及查询一百万条记录的理想方式是什么?

最佳答案

查询一百万条记录的理想方式是使用 IQueryable<T>以确保在需要实际数据之前,您实际上并没有在数据库上执行查询。我非常怀疑您一次需要一百万条记录。

它死锁的原因是你要求 MySQL 服务器从数据库中提取那百万条记录,然后按 EMPLOYEE_ID 排序。然后让您的程序将其返回给您。所以我想死锁来自您的程序等待它完成,并等待您的程序将其读入内存。 MySQL的问题可能与超时问题有关。

var data 的原因section works quickly 是因为你实际上还没有做任何事情,你只是构建了查询。当你调用ToList()然后执行所有的 SQL 和 SQL 的读取。这就是所谓的延迟加载。

我建议按如下方式尝试:

        var data = from employees in dataContext.employee_table
.Include("employee_type")
.Include("employee_status")
orderby employees.EMPLOYEE_ID descending
select employees;

然后,当您真正需要列表中的某些内容时,只需调用

data.Where(/* your filter expression */).ToList()

因此,如果您需要 ID 为 10 的员工。

var employee = data.Where(e => e.ID == 10).ToList();

或者如果你需要所有姓氏以S开头的员工(我不知道你的表是否有姓氏列,只是一个例子)。

var employees = data.Where(e => e.LastName.StartsWith("s")).ToList();

或者,如果您想以 100 位为单位翻阅所有员工

var employees = data.Skip(page * 100).Take(100).ToList();

如果您想进一步延迟数据库调用,则不能调用 ToList()并在需要时使用迭代器。因此,假设您要将姓名以 A 开头的人员的所有工资相加

 var salaries = data.Where(s => s.LastName.StartsWith("A"))

foreach(var employee in salaries)
{
salaryTotal += employee.Salary;
}

这只会做一个看起来像这样的查询

Select Salary From EmployeeTable Where ID = @ID

导致非常快速的查询,仅在您需要时获取信息,并且仅获取您需要的信息。

如果出于某种疯狂的原因,您想实际查询数据库的所有百万条记录。忽略这会占用大量系统资源这一事实,我建议分 block 执行此操作,您可能需要调整 block 大小以获得最佳性能。

一般的想法是执行较小的查询以避免数据库超时问题。

int ChunkSize = 100; //for example purposes
HashSet<Employee> Employees - new HashSet<Employee>;

//Assuming it's exactly 1 Million records

int RecordsToGet = 1000000;

for(record = 0; record <= RecordsToGet; record += ChunkSize)
{
dataContext.EmployeeTable.Skip(record).Take(ChunkSize).ForEach(e => HashSet.Add(e));
}

我选择使用 HashSet<T>因为它们是为大型数据集设计的,但我不知道 1,000,000 个对象的性能如何。

关于c# - 实体模型 .net 从 MySQL 性能问题中查询 100 万条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5290312/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com