Linq表达式中||、|与链式Where的查询结果及执行速度差异问题
三条LINQ查询语句的差异对比
核心结论
三条语句的返回结果、执行逻辑、执行速度均存在明显差异,具体分析如下:
1. 语法与逻辑语义差异
语句1:var results = db.Orders.Where(x => x.Status == Status.Yes || x.Status == Status.No)
- 使用逻辑或运算符
||,属于短路运算:只要左边x.Status == Status.Yes判断为真,就不会执行右边的判断,直接返回真 - 业务语义为筛选所有Status为Yes或者No的订单,满足两个条件任意一个即可命中
语句2:var results = db.Orders.Where(x => x.Status == Status.Yes | x.Status == Status.No)
- 使用按位或运算符
|,没有短路逻辑,无论左边判断结果真假,都会执行两边的表达式 - 针对布尔值判断的场景,最终筛选逻辑和语句1一致,同样是命中Status为Yes或No的订单,仅底层运算逻辑有区别
语句3:var results = db.Orders.Where(x => x.Status == Status.Yes).Where(x => x.Status == Status.No)
- 链式调用两个Where条件,逻辑上等价于逻辑与
&&:需要同时满足Status == Yes和Status == No两个互斥条件 - 因为枚举值Status不可能同时为Yes和No,所以这条语句永远返回空集合
2. 返回结果对比
- 语句1和语句2在数据正常的前提下返回结果一致,都是所有Status为Yes或No的订单
- 语句3永远返回空结果,和前两者完全不同
3. 执行速度对比
这三条语句属于IQueryable类型的LINQ to Entities查询,最终会被ORM翻译成SQL执行,速度差异取决于生成的SQL语句:
- 语句1和语句2在绝大多数主流ORM(EF Core、EF6等)中会被翻译为同一段SQL:
WHERE Status = @Yes OR Status = @No,执行速度完全等价少数极端场景下,部分老旧ORM可能对
|运算符翻译异常,生成按位运算的SQL,导致无法命中Status字段的索引,此时语句2的速度会远慢于语句1 - 语句3会被翻译为
WHERE Status = @Yes AND Status = @No,数据库优化器通常会直接判定该条件永远为假,直接返回空,执行速度反而会比前两者更快,但结果不符合正常业务需求
内容的提问来源于stack exchange,提问作者OrElse
相关产品推荐
相关产品推荐

