EF中的以下LINQ查询(EFCore,v2.2.1)
var x = context.Exchange
.Include(q => q.Input)
.Where(q => q.InputId != 1&&
q.Input.CreatedOnUtc > DateTime.Parse("2019-11-25") &&
q.Input.UserId == 2 &&
q.BotConversationId == 3)
.Distinct()
.OrderBy(q => q.Input.CreatedOnUtc)
.FirstOrDefault()
最终给出了概要分析的SQL结果(简化了)
select * from (
select distinct e.*
from Exchange e, ExchangeInput i
where e.InputId = i.InputId
and e.InputId <> 1
and i.UserId = 2
and e.BotConversationId = 3
)
select * from ExchangeInput
为什么需要执行两个单独的查询?当ExchangeInput可能有数百万行时,第二个查询太可怕了。 当然,这足够了:
select * from (
select distinct e.*, i.CreatedOnUtc
from Exchange e, ExchangeInput i
where e.InputId = i.InputId
and e.InputId <> 1
and i.UserId = 2
and e.BotConversationId = 3
) a
order by a.CreatedOnUtc
此外-按我的期望,将Distinct放在订单后仅给出1个查询。
解决问题很容易。在.Select(...)
之前添加.Distinct
或删除.Distinct()
即可。但是,最初的性能不佳的代码在查看时似乎不会立即成为问题。
答案 0 :(得分:3)
我首先建议不要在Distinct()
之前调用FirstOrDefault()
。当您拥有OrderBy时,“非区别”查询中的第一行应始终与“区别”查询相同。正如您在上一句话中提到的那样,删除Distinct()
似乎只能创建一个查询。
除了您的问题之外,我还建议在查询之外计算DateTime.Parse("2019-11-25")
。那应该允许您将它作为参数传递给数据库服务器,这可能会使查询效率更高。
总而言之,我会尝试:
var dateFilter = DateTime.Parse("2019-11-25");
var x = context.Exchange
.Include(q => q.Input)
.Where(q => q.InputId != 1 &&
q.Input.CreatedOnUtc > dateFilter &&
q.Input.UserId == 2 &&
q.BotConversationId == 3)
.OrderBy(q => q.Input.CreatedOnUtc)
.FirstOrDefault()