LINQ查询OrderBy与Where不同调用顺序的执行差异及性能对比
LINQ两种查询写法的差异对比
执行逻辑差异
我们分两种最常见的LINQ运行场景分开说明:
场景1:LINQ to Objects(操作内存中本地集合)
- 先
OrderBy再Where的写法:
先对全部Person集合执行排序操作,排序完成后再遍历所有排序后的元素,过滤出符合FirstName包含"a"条件的结果。 - 先
Where再OrderBy的写法:
先遍历整个Person集合,过滤出符合条件的元素,再仅对过滤后的小集合执行排序操作。
两种写法最终返回的结果完全一致,因为筛选操作不会改变元素本身的属性值,不管排序在前还是在后,最终符合条件的元素的排序结果是相同的。
场景2:LINQ to Entities(对接数据库,比如EF/EF Core)
两种写法都会被ORM先转换成表达式树,再翻译为SQL语句执行。目前主流的成熟ORM(比如EF Core 3.0以上版本)以及关系型数据库的查询优化器都会自动调整执行顺序,最终生成的SQL都是先执行WHERE过滤,再执行ORDER BY排序,两种写法的实际执行逻辑完全相同。
性能差异
- 内存集合场景下:先
Where再OrderBy的性能远优于反过来的写法。排序的时间复杂度为O(n log n),n是参与排序的元素数量:假设原集合有1万条数据,过滤后只剩1000条符合条件,前者只需要对1000条元素排序,后者需要对1万条元素排序,计算量差了数倍,同时后者还要多一次全量排序后遍历过滤的开销。 - 对接数据库场景下:两种写法性能没有差异,因为最终执行的SQL是完全相同的。
最优写法推荐
不管是哪种场景,都优先选择先写Where过滤、再写OrderBy排序的写法:
- 内存场景下可以获得非常明显的性能提升
- 对接数据库场景下语义更清晰,也可以规避部分小众、不成熟的LINQ提供器没有做查询优化,生成先排序后过滤的低效SQL的问题
底层原理依据
- LINQ to Objects基于迭代器模式执行,方法链的调用顺序就是实际的执行顺序,每一步的输出直接作为下一步的输入,没有内置的执行逻辑优化,所以调用顺序直接决定了执行效率。
- LINQ to Entities会先把方法调用链转换成抽象的表达式树,再由对应的LINQ提供器对表达式树做逻辑优化,最终翻译为SQL时还会经过数据库本身的查询优化器调整执行计划,所以上层的调用顺序不会影响最终的执行逻辑。
内容的提问来源于stack exchange,提问作者Roohallah Azizi
相关产品推荐
相关产品推荐

