如何优化包含子查询计算pscount的C# LINQ查询?
LINQ查询优化方案(针对pscount子查询)
核心问题分析
你当前的pscount是关联子查询,主查询每返回一行数据,就会执行一次子查询统计计数,数据量上升后会因重复查询拖慢整体速度。
优化步骤
1. 预聚合统计,用Join替代关联子查询
先提前计算puntosuministroview的统计结果,再和主查询关联,避免重复执行子查询:
// 预聚合统计需要的计数 var psCountQuery = from p in db.puntosuministroview group p by new { p.concesion_id, p.planificacion_id, p.acometida_id } into g select new { g.Key.concesion_id, g.Key.planificacion_id, g.Key.acometida_id, Count = g.Count() }; // 主查询关联预聚合结果 var q = from finca in db.finca join direccion in db.direccion on finca.direccion_id equals direccion.direccion_id join ambito in db.ambito_geografico on direccion.ambito_id equals (short?)ambito.ambito_id join acometida in db.acometida on finca.acometida_defecto_id equals acometida.acometida_id join planificacion in db.planificacion on finca.planificacion_defecto_id equals planificacion.planificacion_id // 左连接避免无匹配项时丢失主数据 join psCount in psCountQuery on new { finca.concesion_id, finca.planificacion_defecto_id, finca.acometida_defecto_id } equals new { psCount.concesion_id, psCount.planificacion_id, psCount.acometida_id } into psCountGroup from psCount in psCountGroup.DefaultIfEmpty() select new FincaViewModel { direccion = direccion.direccion_postal_1, ambito = ambito.descripcion, acometida = acometida.nombre, // 无匹配项时计数设为0 pscount = psCount?.Count ?? 0, concesion_id = finca.concesion_id, planificacion = planificacion.nombre_planificacion, disponible_contratacion = finca.disponible_contratacion ? General.Si : General.No, };
2. 添加数据库复合索引提升聚合效率
给puntosuministroview(若为表)创建覆盖过滤字段的复合索引:
CREATE NONCLUSTERED INDEX IX_puntosuministroview_Concesion_Planificacion_Acometida ON puntosuministroview (concesion_id, planificacion_id, acometida_id)
如果puntosuministroview是视图,需确保底层表有对应索引,或考虑将其改为索引视图(视业务场景适配)。
3. 简化冗余代码(可选)
原代码中from p in this.db.puntosuministroview select p可直接简化为this.db.puntosuministroview,虽对性能影响不大,但能提升代码简洁性。
额外检查点
- 主查询中用到的外键字段(如
finca.direccion_id、finca.acometida_defecto_id)需确认是否有索引,保证Join操作高效。 - 可通过EF的
ToQueryString()方法查看生成的SQL,对比优化前后的执行计划,验证索引是否被正确调用。
内容的提问来源于stack exchange,提问作者Diego Perez
相关产品推荐
相关产品推荐

