在 EF "sub-query" 中强制 "TOP 100 PERCENT" 可查询

Force "TOP 100 PERCENT" in EF "sub-query" queryable

更新:关于top 100 percent生成更好的查询计划(该计划对于大小合理 top N,可能与参数嗅探有关)。

虽然我仍然认为这个重点问题有其价值,但它 "a useful solution" 不适合我的问题 2,也可能不适合你的问题..


我 运行 遇到一些 SQL 服务器优化不佳的查询。统计数据显示正确,并且 SQL 服务器选择 'worse' 计划对 数百万 条记录执行搜索,即使估计值和实际值相同 - 但是这个问题不是关于那个1

有问题的查询是简化形式:

select * from x
join y on ..
join z on ..
where z.q = ..

但是(显然,因为我更了解基数)以下形式始终导致更好的查询计划:

select * from x
join (
  -- the result set here is 'quite small'
  select top 100 percent *
  from y on ..
  join z on ..
  where z.q = ..) t on ..

在 L2S 中,Take 函数可用于限制为 top N,但我使用这种方法的 "problem" 需要一个 finite/fixed N,这样假设一些查询可能会中断,而不仅仅是 运行 强制实现真的很慢。

虽然我可以为 top N 选择一个 'very large' 值,但具有讽刺意味的是(对于最初的问题),随着 N 值的增加,SQL 查询执行时间增加.预期的中间结果预计只有几十到几百条记录。我当前运行的代码 top 100 然后,如果检测到这样的代码包含太多结果,则再次无限制地运行查询:但这感觉就像一个杂乱无章的.. 在杂乱无章的基础上。

接下来的问题是:EF/L2E/LINQ 查询能否在 EF Queryable 上生成 top 100 percent 的等效项?

(通过 ToList 强制具体化不是一种选择,因为结果应该是 EF 可查询 并且保留在 LINQ to Entities 中,而不是 LINQ to Objects。)

虽然我目前正在处理 EF4,但如果这 [仅] 在更高版本的 EF 中可能,我 接受这样的答案 - 这是有用的知识并且确实回答问题。


1 如果希望用 "don't do that" 或 "alternative" 回答,请将其作为次要答案或放在一边 along 并回答所问的实际问题。否则,请随时使用评论。


2 除了 top 100 percent 没有生成更好的查询计划外,我忘了包含 'core issue' 的问题,这是错误的参数嗅探(实例是 SQL Server 2005).

以下查询需要很长时间才能完成,而直接变量替换运行 "in the blink of an eye" 表明参数嗅探存在问题。

declare @x int
set @x = 19348659

select
op.*
from OrderElement oe
join OrderRatePlan rp on oe.OrdersElementID = rp.OrdersElementID
join OrderPrice op on rp.OrdersRatePlanID = op.OrdersRatePlanID
where oe.OrdersProductID = @x

笨拙但可行的查询

select
  op.*
from OrderPrice op
join (
  -- Choosing a 'small value of N' runs fast and it slows down as the
  -- value of N is increases where N >> 1000 simply "takes too long".
  -- Using TOP 100 PERCENT also "takes too long".
  select top 100
    rp.*
  from OrderElement oe
  join OrderRatePlan rp on oe.OrdersElementID = rp.OrdersElementID
  where oe.OrdersProductID = @x
) rp
on rp.OrdersRatePlanID = op.OrdersRatePlanID

是的,您可以自己查询。

db.SqlQuery<something>("SELECT * FROM x ...");