实体框架 DbContext 过滤的计数查询使用变量非常慢
Posted
技术标签:
【中文标题】实体框架 DbContext 过滤的计数查询使用变量非常慢【英文标题】:Entity Framework DbContext filtered query for count is extremely slow using a variable 【发布时间】:2020-02-07 17:08:25 【问题描述】:使用 ADO.NET 实体数据模型,我在下面针对包含 1800 条记录的表构建了两个查询,其中包含 30 多个字段,产生了惊人的结果。
// Executes slowly, over 6000 ms
int count = context.viewCustomers.AsNoTracking()
.Where(c => c.Cust_ID == _custID).Count();
// Executes instantly, under 20 ms
int count = context.viewCustomers.AsNoTracking()
.Where(c => c.Cust_ID == 625).Count();
我从数据库日志中看到,Entity Framework 提供的查询几乎相同,只是过滤器部分使用了一个参数。将此查询复制到 SSMS 并在其中声明和设置此参数会导致近乎即时的查询,因此它似乎不在数据库端。
有没有人遇到过可以解释发生了什么的情况?我受制于第三方控件,该控件将此命令添加到查询中以尝试限制返回的行数,因此必须获得计数。这用于多个查询,因此需要通用解决方案。不幸的是,它并没有像宣传的那样工作,它似乎只使查询花费的时间是我将整个视图加载到内存中的 5-10 倍。然而,当不使用过滤器时,它就像做梦一样。
这些组件的使用包括源代码,因此我可以更改此行为,但需要考虑可以使用哪些方法来提供可重用的解决方案。
【问题讨论】:
我猜你的表在Cust_ID
列上没有Index
。也许您可以检查并再次确认。
【参考方案1】:
您没有提及模型的设计细节,但如果您只想根据条件计算记录,那么可以通过仅基于一列计算结果集来优化。例如,
int count = context.viewCustomers.AsNoTracking().Where(c => c.Cust_ID == _custID).Count();
如果您设计有 10 列,并且根据上述语句假设返回了 100 条记录,那么针对每个记录结果集包含 10 列未使用的数据。
您可以通过仅计算基于单列的结果集来优化这一点。
int count = context.viewCustomers.AsNoTracking().Where(c => c.Cust_ID == _custID).Select(x=>new x.column).Count();
可以使用其他优化方法,例如使用 count CountAsync
的异步变体。
【讨论】:
以上是关于实体框架 DbContext 过滤的计数查询使用变量非常慢的主要内容,如果未能解决你的问题,请参考以下文章
将 POCO/实体添加到 DbContext 以进行自定义查询/过程,而无需先在实体框架代码中创建表
在Code第一实体框架中将DbContext转换为Datatable