Entity Framework使用Include关联查询时性能大幅下降问题求助
性能问题成因
- 多表关联开销:你在投影中不仅访问了
Server_Items的字段,还访问了Server_Items.Server_Clothes的属性,相当于原单表查询变成了Characters_Inventory、Server_Items、Server_Clothes三张表的JOIN操作,多表关联本身就会提升查询耗时,如果关联字段没有索引,耗时会进一步放大。 - Include语句冗余:使用自定义Select投影时,EF Core会自动根据投影中用到的关联实体字段生成JOIN逻辑,你手动写的
Include(p => p.Server_Items)完全没有作用,只会增加EF表达式解析的额外开销。 - AsSplitQuery不生效:AsSplitQuery仅针对关联加载集合属性的场景拆分查询,你这里都是一对一的引用关联,EF Core不会对单条SELECT投影做拆分,所以开启关闭都不会有性能差异。
- 索引缺失:大概率是筛选字段、关联外键没有建对应索引,导致查询时触发全表扫描,再叠加多表关联的开销,耗时直接增长近20倍。
可行优化方案
- 删除冗余的Include语句,减少EF表达式解析的无用开销。
- 补充索引配置:
- 给
Characters_Inventory表的charId + itemLocation建立联合非聚集索引,覆盖Where条件的筛选逻辑 - 给
Characters_Inventory和Server_Items关联的外键字段、Server_Items和Server_Clothes关联的外键字段建立索引,避免关联时的全表扫描 - 给
Server_Items、Server_Clothes建立覆盖索引:将关联外键作为索引键,把你查询用到的所有字段(如itemType、itemSubType、type、gender等)设为索引包含字段,这样查询可以直接走索引拿数据,不需要回表查聚簇索引,性能提升非常明显。
- 给
- 把
AsNoTracking()替换为AsNoTrackingWithIdentityResolution(),一对一关联查询场景下,该方法比普通AsNoTracking性能高20%左右,避免重复加载相同的关联实体数据。 - 如果
Server_Items、Server_Clothes属于变动频率极低的基础配置表,可以将两表全量数据提前加载到内存缓存中,查询完Characters_Inventory后直接在内存中拼接对应字段,完全避免数据库层面的多表关联,耗时可以降到和单表查询相近的水平。 - 开启EF Core的SQL日志输出,拿到实际生成的SQL语句后到数据库中查看执行计划,确认是否存在全表扫描、索引未命中的问题,针对性调整优化。
内容的提问来源于stack exchange,提问作者Kyuubi D. Dragon
相关产品推荐
相关产品推荐

