EF Core的Split Query(分离查询)是针对关联查询场景设计的性能优化方案,当实体间存在一对多或者多对多关系时,默认的查询方式会将所有关联数据通过一条SQL查询返回,容易产生笛卡尔积,导致数据重复和查询效率下降。Split Query可以把关联查询拆分成多条独立的SQL语句,每条语句只查询对应表的数据,最后在内存中完成关联拼接,有效提升查询性能。

Split Query的工作原理
默认情况下,EF Core执行一对多关联查询时,会生成包含JOIN的SQL语句,一次性获取主表和关联表的所有数据。如果主表有1条记录,关联表有10条对应记录,查询结果会返回10行重复主表数据的记录,既浪费带宽也会增加内存开销。
开启Split Query后,EF Core会生成两条独立的SQL:第一条查询主表数据,第二条查询关联表数据,然后通过主表的主键和关联表的外键在内存中完成匹配,避免了笛卡尔积问题。
如何启用Split Query
全局配置
可以在DbContext的配置阶段全局开启Split Query,这样所有符合条件的查询都会默认使用分离查询模式。
// DbContext配置代码
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// 全局启用Split Query
optionsBuilder.UseSqlServer("Server=.;Database=TestDb;Trusted_Connection=True")
.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
}
单查询配置
如果只需要针对某一次查询开启Split Query,不需要全局配置,可以使用AsSplitQuery扩展方法,该方法只会影响当前查询的行为。
// 单查询开启Split Query示例
var result = await dbContext.Orders
.Include(o => o.OrderItems) // 关联查询订单项
.AsSplitQuery() // 对该查询启用分离查询
.ToListAsync();
一对多场景下的性能对比
我们以一个订单和订单项的一对多关系为例,对比默认查询和Split Query的差异。实体定义如下:
// 订单实体
public class Order
{
public int Id { get; set; }
public string OrderNo { get; set; }
// 一对多关联订单项
public List<OrderItem> OrderItems { get; set; }
}
// 订单项实体
public class OrderItem
{
public int Id { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public int OrderId { get; set; }
// 关联订单
public Order Order { get; set; }
}
默认查询生成的SQL如下,使用LEFT JOIN关联两张表:
SELECT [o].[Id], [o].[OrderNo], [o0].[Id], [o0].[OrderId], [o0].[ProductName], [o0].[Quantity] FROM [Orders] AS [o] LEFT JOIN [OrderItems] AS [o0] ON [o].[Id] = [o0].[OrderId] ORDER BY [o].[Id]
开启Split Query后生成两条SQL:
-- 第一条查询主表订单数据 SELECT [o].[Id], [o].[OrderNo] FROM [Orders] AS [o] ORDER BY [o].[Id] -- 第二条查询关联表订单项数据 SELECT [o0].[Id], [o0].[OrderId], [o0].[ProductName], [o0].[Quantity] FROM [OrderItems] AS [o0] WHERE [o0].[OrderId] IN (1, 2, 3) -- 这里的1,2,3是第一条查询返回的订单Id ORDER BY [o0].[OrderId]
使用注意事项
- Split Query会增加数据库请求次数,如果关联层级非常多,可能导致请求数过多,反而影响性能,需要根据实际场景权衡。
- 如果查询中使用了分页、排序等操作,Split Query的行为和单查询可能不一致,需要提前测试验证结果是否符合预期。
- 对于数据量很小的一对多关联场景,默认的单查询可能效率更高,不需要强行使用Split Query。
- 使用Split Query时,如果主表查询和关联表查询不是在同一个事务中执行,可能出现数据不一致的问题,建议配合事务使用。
适用场景总结
Split Query最适合一对多关联数据量较大、关联后会产生明显笛卡尔积的查询场景,比如订单和订单项、文章和评论这类关系。当关联后的数据行数远多于主表数据行数时,使用Split Query可以明显减少数据传输量,提升查询响应速度。如果是简单的单表查询或者一对一关联查询,不需要使用该功能。
EF CoreSplit_Query一对多查询查询性能优化修改时间:2026-06-13 04:15:14