在 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 ...");
更新:我误关于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 ...");