在EF Core与SQL Server中Where()放OrderBy()前能否提升查询性能?
EF Core中OrderBy与Where的顺序对SQL Server查询性能的影响
直接给结论:绝大多数场景下两者性能没有差异,仅EF Core 3.0之前的老旧版本可能存在明显性能差距。
底层逻辑说明
EF Core的核心能力是将C# LINQ表达式翻译为原生SQL语句,最终交由SQL Server的查询优化器执行,两种写法的差异本质是LINQ表达式顺序是否会影响最终生成的SQL执行效率。
高版本EF Core(3.0+)无性能差异
你给出的两种写法:
先排序后过滤的写法:
var list = await dbContext.MyTable .OrderByDescending(x => x.Timestamp) .Where(x => x.Something == someVar && x.Succeeded) .ToListAsync() .ConfigureAwait(false);
先过滤后排序的写法:
var list = await dbContext.MyTable .Where(x => x.Something == someVar && x.Succeeded) .OrderByDescending(x => x.Timestamp) .ToListAsync() .ConfigureAwait(false);
在EF Core 3.0及以上版本中,查询翻译器会自动优化表达式树的逻辑顺序,两种写法最终生成的SQL完全一致,格式大概如下:
SELECT * FROM [MyTable] WHERE [Something] = @someVar AND [Succeeded] = 1 ORDER BY [Timestamp] DESC
SQL Server生成的执行计划完全相同,性能没有任何区别。
老旧版本EF Core(3.0之前)可能存在性能差距
EF Core 3.0之前的版本查询翻译器逻辑不完善,小概率会把先写OrderBy再写Where的LINQ翻译为嵌套子查询,类似如下SQL:
SELECT * FROM ( SELECT * FROM [MyTable] ORDER BY [Timestamp] DESC ) AS [t] WHERE [t].[Something] = @someVar AND [t].[Succeeded] = 1
这种写法会先对整张表的所有数据执行排序,再做过滤,如果MyTable数据量很大、过滤后仅保留少量数据,会浪费大量CPU、内存资源做无用的全表排序,性能远差于先过滤再排序的写法。
推荐写法
无论你使用哪个版本的EF Core,都建议统一把过滤类操作(Where、Take、Skip等缩小数据集的操作)放在排序、投影操作之前:
- 符合SQL的逻辑执行顺序,代码可读性更高
- 完全规避老旧版本翻译缺陷导致的性能问题
内容的提问来源于stack exchange,提问作者eddex
相关产品推荐
相关产品推荐

